summaryrefslogtreecommitdiffstats
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/qapplication.cpp132
-rw-r--r--src/kernel/qapplication.h13
-rw-r--r--src/kernel/qapplication_x11.cpp4
-rw-r--r--src/kernel/qdragobject.cpp6
-rw-r--r--src/kernel/qevent.h2
-rw-r--r--src/kernel/qeventloop.cpp32
-rw-r--r--src/kernel/qeventloop.h37
-rw-r--r--src/kernel/qeventloop_glib_p.h68
-rw-r--r--src/kernel/qeventloop_unix.cpp3
-rw-r--r--src/kernel/qeventloop_unix_glib.cpp42
-rw-r--r--src/kernel/qeventloop_x11.cpp104
-rw-r--r--src/kernel/qeventloop_x11_glib.cpp691
-rw-r--r--src/kernel/qimage.cpp1
-rw-r--r--src/kernel/qinputcontext.cpp9
-rw-r--r--src/kernel/qinputcontext_x11.cpp2
-rw-r--r--src/kernel/qjpegio.cpp2
-rw-r--r--src/kernel/qnetworkprotocol.cpp8
-rw-r--r--src/kernel/qnetworkprotocol.h4
-rw-r--r--src/kernel/qobject.cpp328
-rw-r--r--src/kernel/qobject.h16
-rw-r--r--src/kernel/qpaintdevice_x11.cpp15
-rw-r--r--src/kernel/qprocess_unix.cpp8
-rw-r--r--src/kernel/qscriptengine_x11.cpp12
-rw-r--r--src/kernel/qstyle.h13
-rw-r--r--src/kernel/qthread.cpp17
-rw-r--r--src/kernel/qthread.h14
-rw-r--r--src/kernel/qthread_unix.cpp46
-rw-r--r--src/kernel/qwidget.cpp9
28 files changed, 1078 insertions, 560 deletions
diff --git a/src/kernel/qapplication.cpp b/src/kernel/qapplication.cpp
index 51aa247..5b43301 100644
--- a/src/kernel/qapplication.cpp
+++ b/src/kernel/qapplication.cpp
@@ -68,6 +68,7 @@
#if defined(QT_THREAD_SUPPORT)
# include "qmutex.h"
# include "qthread.h"
+# include <private/qthreadinstance_p.h>
#endif // QT_THREAD_SUPPORT
#include <stdlib.h>
@@ -383,7 +384,25 @@ Q_EXPORT Qt::HANDLE qt_get_application_thread_id()
}
#endif // QT_THREAD_SUPPORT
+#ifndef QT_THREAD_SUPPORT
QEventLoop *QApplication::eventloop = 0; // application event loop
+#endif
+
+#ifdef QT_THREAD_SUPPORT
+QEventLoop* QApplication::currentEventLoop() {
+ QThread* thread = QThread::currentThreadObject();
+ if (thread) {
+ if (thread->d) {
+ return thread->d->eventLoop;
+ }
+ }
+ return NULL;
+}
+#else
+QEventLoop* QApplication::currentEventLoop() {
+ return QApplication::eventloop;
+}
+#endif
#ifndef QT_NO_ACCEL
extern bool qt_dispatchAccelEvent( QWidget*, QKeyEvent* ); // def in qaccel.cpp
@@ -516,6 +535,41 @@ QClipboard *qt_clipboard = 0; // global clipboard object
#endif
QWidgetList * qt_modal_stack=0; // stack of modal widgets
+#ifdef QT_THREAD_SUPPORT
+// thread wrapper for the main() thread
+class QCoreApplicationThread : public QThread
+{
+public:
+ inline QCoreApplicationThread()
+ {
+ QThreadInstance::setCurrentThread(this);
+
+ // thread should be running and not finished for the lifetime
+ // of the application (even if QCoreApplication goes away)
+ d->running = true;
+ d->finished = false;
+ d->eventLoop = NULL;
+ }
+ inline ~QCoreApplicationThread()
+ {
+ // avoid warning from QThread
+ d->running = false;
+ }
+private:
+ inline void run()
+ {
+ // this function should never be called, it is implemented
+ // only so that we can instantiate the object
+ qFatal("QCoreApplicationThread: internal error");
+ }
+};
+
+static QCoreApplicationThread qt_main_thread;
+static QThread *mainThread() { return &qt_main_thread; }
+#else
+static QThread* mainThread() { return QThread::currentThread(); }
+#endif
+
// Definitions for posted events
struct QPostEvent {
QPostEvent( QObject *r, QEvent *e ): receiver( r ), event( e ) {}
@@ -818,8 +872,8 @@ void QApplication::construct( int &argc, char **argv, Type type )
initialize( argc, argv );
if ( qt_is_gui_used )
qt_maxWindowRect = desktop()->rect();
- if ( eventloop )
- eventloop->appStartingUp();
+ if ( currentEventLoop() )
+ currentEventLoop()->appStartingUp();
}
/*!
@@ -874,8 +928,8 @@ QApplication::QApplication( Display* dpy, HANDLE visual, HANDLE colormap )
if ( qt_is_gui_used )
qt_maxWindowRect = desktop()->rect();
- if ( eventloop )
- eventloop->appStartingUp();
+ if ( currentEventLoop() )
+ currentEventLoop()->appStartingUp();
}
/*!
@@ -916,13 +970,26 @@ QApplication::QApplication(Display *dpy, int argc, char **argv,
if ( qt_is_gui_used )
qt_maxWindowRect = desktop()->rect();
- if ( eventloop )
- eventloop->appStartingUp();
+ if ( currentEventLoop() )
+ currentEventLoop()->appStartingUp();
}
#endif // Q_WS_X11
+#ifdef QT_THREAD_SUPPORT
+QThread* QApplication::guiThread() {
+ return mainThread();
+}
+
+bool QApplication::isGuiThread() {
+ return (QThread::currentThreadObject() == guiThread());
+}
+#else
+bool QApplication::isGuiThread() {
+ return true;
+}
+#endif
void QApplication::init_precmdline()
{
@@ -1030,8 +1097,8 @@ QApplication::~QApplication()
}
#endif
- if ( eventloop )
- eventloop->appClosingDown();
+ if ( currentEventLoop() )
+ currentEventLoop()->appClosingDown();
if ( postRList ) {
QVFuncList::Iterator it = postRList->begin();
while ( it != postRList->end() ) { // call post routines
@@ -2698,8 +2765,28 @@ bool QApplication::internalNotify( QObject *receiver, QEvent * e)
}
- if (!handled)
+ if (!handled) {
+#if defined(QT_THREAD_SUPPORT)
+ int locklevel = 0;
+ int llcount;
+ if (QApplication::qt_mutex) {
+ QApplication::qt_mutex->lock(); // 1 of 2
+ locklevel = qt_mutex->level() - 1;
+ for (llcount=0; llcount<locklevel; llcount++) {
+ QApplication::qt_mutex->unlock();
+ }
+ QApplication::qt_mutex->unlock(); // 2 of 2
+ }
+#endif
consumed = receiver->event( e );
+#if defined(QT_THREAD_SUPPORT)
+ if (QApplication::qt_mutex) {
+ for (llcount=0; llcount<locklevel; llcount++) {
+ QApplication::qt_mutex->lock();
+ }
+ }
+#endif
+ }
e->spont = FALSE;
return consumed;
}
@@ -2793,9 +2880,10 @@ void QApplication::processOneEvent()
*/
QEventLoop *QApplication::eventLoop()
{
- if ( !eventloop && !is_app_closing )
+ if ( !currentEventLoop() && !is_app_closing ) {
(void) new QEventLoop( qApp, "default event loop" );
- return eventloop;
+ }
+ return currentEventLoop();
}
@@ -3263,8 +3351,23 @@ void QApplication::postEvent( QObject *receiver, QEvent *event )
l->append( pe );
globalPostedEvents->append( pe );
- if (eventloop)
- eventloop->wakeUp();
+#ifdef QT_THREAD_SUPPORT
+ if ( event->type() == QEvent::MetaCall ) {
+ // Wake up the receiver thread event loop
+ QThread* thread = receiver->contextThreadObject();
+ if (thread) {
+ if (thread->d) {
+ if (thread->d->eventLoop) {
+ thread->d->eventLoop->wakeUp();
+ }
+ }
+ }
+ return;
+ }
+#endif
+
+ if (currentEventLoop())
+ currentEventLoop()->wakeUp();
}
@@ -3326,7 +3429,8 @@ void QApplication::sendPostedEvents( QObject *receiver, int event_type )
&& ( receiver == 0 // we send to all receivers
|| receiver == pe->receiver ) // we send to THAT receiver
&& ( event_type == 0 // we send all types
- || event_type == pe->event->type() ) ) { // we send THAT type
+ || event_type == pe->event->type() ) // we send THAT type
+ && ( (!pe->receiver) || (pe->receiver->contextThreadObject() == QThread::currentThreadObject()) ) ) { // only send if active thread is receiver object owning thread
// first, we diddle the event so that we can deliver
// it, and that noone will try to touch it later.
pe->event->posted = FALSE;
diff --git a/src/kernel/qapplication.h b/src/kernel/qapplication.h
index c34ff45..5611164 100644
--- a/src/kernel/qapplication.h
+++ b/src/kernel/qapplication.h
@@ -63,6 +63,7 @@ class QWSDecoration;
#ifdef QT_THREAD_SUPPORT
class QMutex;
+class QThread;
#endif // QT_THREAD_SUPPORT
@@ -369,7 +370,9 @@ private:
#ifndef QT_NO_CURSOR
static QCursor *app_cursor;
#endif
+#ifndef QT_THREAD_SUPPORT
static QEventLoop* eventloop;
+#endif
static int app_tracking;
static bool is_app_running;
static bool is_app_closing;
@@ -425,6 +428,7 @@ private:
static void removePostedEvent( QEvent * );
static void removePostedEvents( QObject *receiver, int event_type );
+ friend class QObject;
friend class QWidget;
friend class QETWidget;
friend class QDialog;
@@ -444,6 +448,15 @@ private: // Disabled copy constructor and operator=
QApplication( const QApplication & );
QApplication &operator=( const QApplication & );
#endif
+
+private:
+ static QEventLoop* currentEventLoop();
+
+public:
+#ifdef QT_THREAD_SUPPORT
+ static QThread* guiThread();
+#endif
+ static bool isGuiThread();
};
inline int QApplication::argc() const
diff --git a/src/kernel/qapplication_x11.cpp b/src/kernel/qapplication_x11.cpp
index 2873b9e..c2c0288 100644
--- a/src/kernel/qapplication_x11.cpp
+++ b/src/kernel/qapplication_x11.cpp
@@ -430,7 +430,7 @@ static bool qt_x11EventFilter( XEvent* ev )
//XIM qt_xim = 0;
Q_EXPORT XIMStyle qt_xim_style = 0;
Q_EXPORT XIMStyle qt_xim_preferred_style = 0;
-Q_EXPORT static XIMStyle xim_default_style = XIMPreeditCallbacks | XIMStatusNothing;
+static XIMStyle xim_default_style = XIMPreeditCallbacks | XIMStatusNothing;
#endif
Q_EXPORT int qt_ximComposingKeycode=0;
@@ -5889,7 +5889,7 @@ static Bool qt_net_wm_sync_request_scanner(Display*, XEvent* event, XPointer arg
{
return (event->type == ClientMessage && event->xclient.window == *(Window*)arg
&& event->xclient.message_type == qt_wm_protocols
- && event->xclient.data.l[ 0 ] == qt_net_wm_sync_request );
+ && ((unsigned int)event->xclient.data.l[ 0 ]) == qt_net_wm_sync_request );
}
#endif
diff --git a/src/kernel/qdragobject.cpp b/src/kernel/qdragobject.cpp
index 4f3353b..d48d79f 100644
--- a/src/kernel/qdragobject.cpp
+++ b/src/kernel/qdragobject.cpp
@@ -1749,9 +1749,9 @@ QColorDrag::QColorDrag( QWidget *dragsource, const char *name )
void QColorDrag::setColor( const QColor &col )
{
- short r = (col.red() << 8) | col.red();
- short g = (col.green() << 8) | col.green();
- short b = (col.blue() << 8) | col.blue();
+ unsigned short r = (col.red() << 8) | col.red();
+ unsigned short g = (col.green() << 8) | col.green();
+ unsigned short b = (col.blue() << 8) | col.blue();
// make sure we transmit data in network order
r = htons(r);
diff --git a/src/kernel/qevent.h b/src/kernel/qevent.h
index 6512b9a..9587b8f 100644
--- a/src/kernel/qevent.h
+++ b/src/kernel/qevent.h
@@ -137,6 +137,8 @@ public:
HelpRequest = 95, // CE (?) button pressed
WindowStateChange = 96, // window state has changed
IconDrag = 97, // proxy icon dragged
+ MetaCall = 98, // meta method call (internal)
+ ThreadChange = 99, // thread changed
User = 1000, // first user event id
MaxUser = 65535 // last user event id
};
diff --git a/src/kernel/qeventloop.cpp b/src/kernel/qeventloop.cpp
index 1f6a130..5eadb9e 100644
--- a/src/kernel/qeventloop.cpp
+++ b/src/kernel/qeventloop.cpp
@@ -41,6 +41,11 @@
#include "qapplication.h"
#include "qdatetime.h"
+#ifdef QT_THREAD_SUPPORT
+# include "qthread.h"
+# include "qthreadinstance_p.h"
+#endif
+
/*!
\class QEventLoop
\brief The QEventLoop class manages the event queue.
@@ -100,15 +105,27 @@ QEventLoop::QEventLoop( QObject *parent, const char *name )
: QObject( parent, name )
{
#if defined(QT_CHECK_STATE)
- if ( QApplication::eventloop )
- qFatal( "QEventLoop: there must be only one event loop object. \nConstruct it before QApplication." );
- // for now ;)
+ if ( QApplication::currentEventLoop() )
+ qFatal( "QEventLoop: there must be only one event loop object per thread. \nIf this is supposed to be the main GUI event loop, construct it before QApplication." );
+ if (!QThread::currentThreadObject()) {
+ qFatal( "QEventLoop: this object can only be used in threads constructed via QThread." );
+ }
#endif // QT_CHECK_STATE
d = new QEventLoopPrivate;
init();
+
+#ifdef QT_THREAD_SUPPORT
+ QThread* thread = QThread::currentThreadObject();
+ if (thread) {
+ if (thread->d) {
+ thread->d->eventLoop = this;
+ }
+ }
+#else
QApplication::eventloop = this;
+#endif
}
/*!
@@ -118,7 +135,16 @@ QEventLoop::~QEventLoop()
{
cleanup();
delete d;
+#ifdef QT_THREAD_SUPPORT
+ QThread* thread = QThread::currentThreadObject();
+ if (thread) {
+ if (thread->d) {
+ thread->d->eventLoop = 0;
+ }
+ }
+#else
QApplication::eventloop = 0;
+#endif
}
/*!
diff --git a/src/kernel/qeventloop.h b/src/kernel/qeventloop.h
index 25f80cd..a3ee01d 100644
--- a/src/kernel/qeventloop.h
+++ b/src/kernel/qeventloop.h
@@ -102,25 +102,6 @@ public:
virtual void wakeUp();
-#ifdef Q_QDOC
-#else // Q_QDOC
-#if defined(QT_USE_GLIBMAINLOOP)
-
- // glib main loop support
-
- /* internal: used to fit glib-main-loop gsource concept */
-
- bool gsourcePrepare(GSource *gs, int * timeout);
- bool gsourceCheck(GSource * gs);
- bool gsourceDispatch(GSource * gs);
-
- bool processX11Events();
-
- // end glib main loop support
-
-#endif //QT_USE_GLIBMAINLOOP
-#endif // Q_QDOC
-
void setSingleToolkitEventHandling(bool enabled);
signals:
@@ -145,6 +126,24 @@ private:
QEventLoopPrivate *d;
friend class QApplication;
+
+#ifdef Q_QDOC
+#else // Q_QDOC
+#if defined(QT_USE_GLIBMAINLOOP)
+
+ // glib main loop support
+ /* internal: used to fit glib-main-loop gsource concept */
+public:
+ bool gsourcePrepare(GSource *gs, int * timeout);
+ bool gsourceCheck(GSource * gs);
+ bool gsourceDispatch(GSource * gs);
+
+ bool processX11Events();
+
+ // end glib main loop support
+
+#endif //QT_USE_GLIBMAINLOOP
+#endif // Q_QDOC
};
#endif // QEVENTLOOP_H
diff --git a/src/kernel/qeventloop_glib_p.h b/src/kernel/qeventloop_glib_p.h
index 7de324d..663f20e 100644
--- a/src/kernel/qeventloop_glib_p.h
+++ b/src/kernel/qeventloop_glib_p.h
@@ -84,49 +84,51 @@ struct QSockNotGPollFD
class QEventLoopPrivate
{
public:
- QEventLoopPrivate()
- {
- reset();
- }
-
- void reset() {
- looplevel = 0;
- quitcode = 0;
- quitnow = FALSE;
- exitloop = FALSE;
- shortcut = FALSE;
- singletoolkit = TRUE;
- }
-
- int looplevel;
- int quitcode;
- unsigned int quitnow : 1;
- unsigned int exitloop : 1;
- unsigned int shortcut : 1;
-
+ QEventLoopPrivate()
+ {
#if defined(Q_WS_X11)
- int xfd;
-
- GPollFD x_gPollFD;
-
+ xfd = -1;
+ x_gPollFD.fd = -1;
#endif // Q_WS_X11
+ reset();
+ }
+
+ void reset() {
+ looplevel = 0;
+ quitcode = 0;
+ quitnow = FALSE;
+ exitloop = FALSE;
+ shortcut = FALSE;
+ singletoolkit = TRUE;
+ }
+
+ int looplevel;
+ int quitcode;
+ unsigned int quitnow : 1;
+ unsigned int exitloop : 1;
+ unsigned int shortcut : 1;
- int thread_pipe[2];
+#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;
-
+ QPtrList<QSockNotGPollFD> sn_list;
+
+ // pending socket notifiers list
+ QPtrList<QSockNotGPollFD> sn_pending_list;
+
// store flags for one iteration
- uint pev_flags;
-
+ uint pev_flags;
+
// My GSource
-
GSource * gSource;
bool singletoolkit;
+ // main context
+ GMainContext *ctx;
};
#endif // QEVENTLOOP_GLIB_P_H
diff --git a/src/kernel/qeventloop_unix.cpp b/src/kernel/qeventloop_unix.cpp
index b0ad8b9..80c8f29 100644
--- a/src/kernel/qeventloop_unix.cpp
+++ b/src/kernel/qeventloop_unix.cpp
@@ -40,6 +40,7 @@
#include "qeventloop.h"
#include "qapplication.h"
#include "qbitarray.h"
+#include "qmutex.h"
#include <stdlib.h>
#include <sys/types.h>
@@ -561,6 +562,8 @@ int QEventLoop::activateTimers()
n_act++;
QTimerEvent e( t->id );
QApplication::sendEvent( t->obj, &e ); // send event
+ if ( !timerList ) // sendEvent allows other threads to execute, therefore we must check for list existence when it returns!
+ return 0;
if ( timerList->findRef( begin ) == -1 )
begin = 0;
}
diff --git a/src/kernel/qeventloop_unix_glib.cpp b/src/kernel/qeventloop_unix_glib.cpp
index 6852f6b..6a890ce 100644
--- a/src/kernel/qeventloop_unix_glib.cpp
+++ b/src/kernel/qeventloop_unix_glib.cpp
@@ -44,6 +44,7 @@
#include "qeventloop.h"
#include "qapplication.h"
#include "qbitarray.h"
+#include "qmutex.h"
#include <stdlib.h>
#include <sys/types.h>
@@ -369,9 +370,9 @@ void QEventLoop::registerSocketNotifier( QSocketNotifier *notifier )
return;
}
- #ifdef DEBUG_QT_GLIBMAINLOOP
- printf("register socket notifier %d\n", sockfd);
- #endif
+#ifdef DEBUG_QT_GLIBMAINLOOP
+ printf("register socket notifier %d\n", sockfd);
+#endif
QPtrList<QSockNotGPollFD> *list = &d->sn_list;
QSockNotGPollFD *sn;
@@ -424,9 +425,9 @@ void QEventLoop::unregisterSocketNotifier( QSocketNotifier *notifier )
return;
}
- #ifdef DEBUG_QT_GLIBMAINLOOP
- printf("unregister socket notifier %d\n", sockfd);
- #endif
+#ifdef DEBUG_QT_GLIBMAINLOOP
+ printf("unregister socket notifier %d\n", sockfd);
+#endif
QPtrList<QSockNotGPollFD> *list = &d->sn_list;
QSockNotGPollFD *sn;
@@ -457,9 +458,9 @@ void QEventLoop::setSocketNotifierPending( QSocketNotifier *notifier )
return;
}
- #ifdef DEBUG_QT_GLIBMAINLOOP
- printf("set socket notifier pending %d\n", sockfd);
- #endif
+#ifdef DEBUG_QT_GLIBMAINLOOP
+ printf("set socket notifier pending %d\n", sockfd);
+#endif
QPtrList<QSockNotGPollFD> *list = &d->sn_list;
QSockNotGPollFD *sn;
@@ -505,7 +506,9 @@ void QEventLoop::wakeUp()
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 );
+ if (::write( d->thread_pipe[1], &c, 1 ) < 0) {
+ // Failed!
+ }
}
}
@@ -576,17 +579,14 @@ int QEventLoop::activateSocketNotifiers()
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++;
- }
+ 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;
diff --git a/src/kernel/qeventloop_x11.cpp b/src/kernel/qeventloop_x11.cpp
index 833be69..5ee41ca 100644
--- a/src/kernel/qeventloop_x11.cpp
+++ b/src/kernel/qeventloop_x11.cpp
@@ -146,55 +146,57 @@ bool QEventLoop::processEvents( ProcessEventsFlags flags )
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;
+ if (QApplication::isGuiThread()) {
+ // 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;
}
-
- default: break;
- }
}
-
- nevents++;
- if ( qApp->x11ProcessEvent( &event ) == 1 )
- return TRUE;
- }
}
}
@@ -261,7 +263,7 @@ bool QEventLoop::processEvents( ProcessEventsFlags flags )
FD_ZERO( &d->sn_vec[2].select_fds );
}
- if ( qt_is_gui_used ) {
+ if ( qt_is_gui_used && QApplication::isGuiThread() ) {
// select for events on the event socket - only on X11
FD_SET( d->xfd, &d->sn_vec[0].select_fds );
highest = QMAX( highest, d->xfd );
@@ -282,7 +284,8 @@ bool QEventLoop::processEvents( ProcessEventsFlags flags )
// 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();
+ if ( locker.mutex() ) locker.mutex()->unlock();
+ else return false;
#endif
int nsel;
@@ -296,7 +299,8 @@ bool QEventLoop::processEvents( ProcessEventsFlags flags )
// relock the GUI mutex before processing any pending events
#if defined(QT_THREAD_SUPPORT)
- locker.mutex()->lock();
+ if ( locker.mutex() ) locker.mutex()->lock();
+ else return false;
#endif
// we are awake, broadcast it
diff --git a/src/kernel/qeventloop_x11_glib.cpp b/src/kernel/qeventloop_x11_glib.cpp
index 59ab8a1..877ff44 100644
--- a/src/kernel/qeventloop_x11_glib.cpp
+++ b/src/kernel/qeventloop_x11_glib.cpp
@@ -39,7 +39,6 @@
**
**********************************************************************/
-
#include "qeventloop_glib_p.h" // includes qplatformdefs.h
#include "qeventloop.h"
#include "qapplication.h"
@@ -49,58 +48,85 @@
#if defined(QT_THREAD_SUPPORT)
# include "qmutex.h"
+# include "qthread.h"
#endif // QT_THREAD_SUPPORT
#include <errno.h>
#include <glib.h>
+// #define DEBUG_QT_GLIBMAINLOOP 1
+
// Qt-GSource Structure and Callbacks
typedef struct {
- GSource source;
- QEventLoop * qeventLoop;
+ GSource source;
+ QEventLoop * qeventLoop;
} QtGSource;
-static gboolean qt_gsource_prepare ( GSource *source,
- gint *timeout );
+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 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
+ 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 )
+ gint *timeout )
{
- QtGSource * qtGSource;
- qtGSource = (QtGSource*) source;
- return qtGSource->qeventLoop->gsourcePrepare(source, timeout);
+ QtGSource * qtGSource = (QtGSource*) source;
+ QEventLoop* candidateEventLoop = qtGSource->qeventLoop;
+ QEventLoop* activeThreadEventLoop = QApplication::eventLoop();
+
+ if (candidateEventLoop == activeThreadEventLoop) {
+ return candidateEventLoop->gsourcePrepare(source, timeout);
+ }
+ else {
+ // Prepare failed
+ return FALSE;
+ }
}
static gboolean qt_gsource_check ( GSource *source )
{
- QtGSource * qtGSource = (QtGSource*) source;
- return qtGSource->qeventLoop->gsourceCheck(source);
+ QtGSource * qtGSource = (QtGSource*) source;
+ QEventLoop* candidateEventLoop = qtGSource->qeventLoop;
+ QEventLoop* activeThreadEventLoop = QApplication::eventLoop();
+
+ if (candidateEventLoop == activeThreadEventLoop) {
+ return candidateEventLoop->gsourceCheck(source);
+ }
+ else {
+ // Check failed
+ return FALSE;
+ }
}
static gboolean qt_gsource_dispatch ( GSource *source,
GSourceFunc callback, gpointer user_data )
{
- Q_UNUSED(callback);
- Q_UNUSED(user_data);
+ Q_UNUSED(callback);
+ Q_UNUSED(user_data);
- QtGSource * qtGSource = (QtGSource*) source;
- return qtGSource->qeventLoop->gsourceDispatch(source);
+ QtGSource * qtGSource = (QtGSource*) source;
+ QEventLoop* candidateEventLoop = qtGSource->qeventLoop;
+ QEventLoop* activeThreadEventLoop = QApplication::eventLoop();
+
+ if (candidateEventLoop == activeThreadEventLoop) {
+ return candidateEventLoop->gsourceDispatch(source);
+ }
+ else {
+ // Dispatch failed
+ return FALSE;
+ }
}
@@ -134,339 +160,329 @@ 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 );
+ 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 );
- }
+ 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 );
+ 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 );
- }
+ 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
- if (pipe( d->thread_pipe ) < 0) {
- // Error!
- }
- 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;
-
+ // initialize the common parts of the event loop
+ if (pipe( d->thread_pipe ) < 0) {
+ // Error!
+ }
+ 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 && QApplication::isGuiThread() ) {
+ d->xfd = XConnectionNumber( QPaintDevice::x11AppDisplay() );
+ }
+
+ // new main context for thread
+ d->ctx = g_main_context_new();
+ g_main_context_push_thread_default(d->ctx);
+
+ // 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 (d->ctx, 1);
+ g_source_attach( (GSource*)qtGSource, d->ctx );
+ d->gSource = (GSource*)qtGSource;
+
// poll for X11 events
-
- if ( qt_is_gui_used ) {
-
-
+ if ( qt_is_gui_used && QApplication::isGuiThread() ) {
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);
- }
+ d->x_gPollFD.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+ 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;
+ d->threadPipe_gPollFD.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
g_source_add_poll(d->gSource, &d->threadPipe_gPollFD);
- #ifdef DEBUG_QT_GLIBMAINLOOP
- printf("inside init(2)\n");
- #endif
+#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 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;
+
+ // unref the main context
+ g_main_context_unref(d->ctx);
- // 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;
+#ifdef DEBUG_QT_GLIBMAINLOOP
+ printf("inside processEvents(1) looplevel=%d\n", d->looplevel );
+#endif
- d->pev_flags = flags;
-
- rval = g_main_context_iteration(NULL, flags & WaitForMore ? TRUE : FALSE);
-
- d->pev_flags = save_flags;
+ ProcessEventsFlags save_flags;
+ int rval;
+ save_flags = d->pev_flags;
+
+ d->pev_flags = flags;
+
+ rval = g_main_context_iteration(d->ctx, flags & WaitForMore ? TRUE : FALSE);
- #ifdef DEBUG_QT_GLIBMAINLOOP
- printf("inside processEvents(2) looplevel=%d rval=%d\n", d->looplevel, rval );
- #endif
+ d->pev_flags = save_flags;
- return rval; // were events processed?
+#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;
+ // process events from the X server
+ XEvent event;
+ int nevents = 0;
#if defined(QT_THREAD_SUPPORT)
- QMutexLocker locker( QApplication::qt_mutex );
+ 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;
+ // handle gui and posted events
+ if ( qt_is_gui_used ) {
+ QApplication::sendPostedEvents();
+
+ if (QApplication::isGuiThread()) {
+ // 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;
+ }
+ }
}
-
- default: break;
- }
}
-
- nevents++;
- if ( qApp->x11ProcessEvent( &event ) == 1 )
- return TRUE;
- }
}
- }
+
+ if ( d->shortcut ) {
+ return FALSE;
+ }
- if ( d->shortcut ) {
+ 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;
- }
-
- 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)
{
Q_UNUSED(gs);
- #ifdef DEBUG_QT_GLIBMAINLOOP
- printf("inside gsourcePrepare(1)\n");
- #endif
+#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 );
+ 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
+ // 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;
}
- } else {
- QPtrListIterator<QSockNotGPollFD> it( d->sn_list );
- QSockNotGPollFD *sn;
- while ( (sn=it.current()) ) {
- ++it;
- sn->gPollFD.events = 0; // delete poll events
+ }
+
+ // 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();
-
+#ifdef DEBUG_QT_GLIBMAINLOOP
+ printf("inside gsourcePrepare(2) canwait=%d\n", canWait);
+#endif
- 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
+ if ( canWait ) {
+ emit aboutToBlock();
+ }
- #ifdef DEBUG_QT_GLIBMAINLOOP
- printf("inside gsourcePrepare(2.1) canwait=%d\n", canWait);
- #endif
+ if ( qt_preselect_handler ) {
+ QVFuncList::Iterator it, end = qt_preselect_handler->end();
+ for ( it = qt_preselect_handler->begin(); it != end; ++it )
+ (**it)();
+ }
+#ifdef DEBUG_QT_GLIBMAINLOOP
+ printf("inside gsourcePrepare(2.1) canwait=%d\n", canWait);
+#endif
+
// do we have to dispatch events?
- if (hasPendingEvents()) {
+ if (hasPendingEvents()) {
*timeout = 0; // no time to stay in poll
-
- #ifdef DEBUG_QT_GLIBMAINLOOP
- printf("inside gsourcePrepare(3a)\n");
- #endif
-
+#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
-
-
+#ifdef DEBUG_QT_GLIBMAINLOOP
+ printf("inside gsourcePrepare(3b) timeout=%d \n", *timeout);
+#endif
return FALSE;
}
-
- // else timeout >=0
+
+ // 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
-
+#ifdef DEBUG_QT_GLIBMAINLOOP
+ printf("inside gsourcePrepare(3c) timeout=%d \n", *timeout);
+#endif
- return FALSE;
+ return FALSE;
}
bool QEventLoop::gsourceCheck(GSource *gs) {
Q_UNUSED(gs);
- #ifdef DEBUG_QT_GLIBMAINLOOP
- printf("inside gsourceCheck(1)\n");
- #endif
-
+#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 )
@@ -476,45 +492,43 @@ bool QEventLoop::gsourceCheck(GSource *gs) {
//}
if (d->x_gPollFD.revents) {
- #ifdef DEBUG_QT_GLIBMAINLOOP
- printf("inside gsourceCheck(2) xfd!\n");
- #endif
+#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
+ 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
+ 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?
+ // 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;
+ }
- 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
+ // nothing to dispatch
+#ifdef DEBUG_QT_GLIBMAINLOOP
+ printf("inside gsourceCheck(2) nothing to dispatch!\n");
+#endif
- return FALSE;
+ return FALSE;
}
@@ -526,44 +540,41 @@ bool QEventLoop::gsourceDispatch(GSource *gs) {
QMutexLocker locker( QApplication::qt_mutex );
#endif
#if defined(QT_THREAD_SUPPORT)
- locker.mutex()->lock();
+ if (locker.mutex()) 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
+#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;
- if (::read( d->thread_pipe[0], &c, 1 ) < 0) {
- // Error!
- }
- }
+ char c;
+ if (::read( d->thread_pipe[0], &c, 1 ) < 0) {
+ // Error!
+ }
+ }
- if ( qt_postselect_handler ) {
- QVFuncList::Iterator it, end = qt_postselect_handler->end();
- for ( it = qt_postselect_handler->begin(); it != end; ++it )
- (**it)();
- }
+ 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 )) {
+ // 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 ) {
@@ -572,40 +583,38 @@ bool QEventLoop::gsourceDispatch(GSource *gs) {
sn = list->next();
}
// }
-
+
nevents += activateSocketNotifiers();
- }
+ }
- // activate timers
- if ( ! ( flags & 0x08 ) ) {
+ // 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
-
+#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();
+#if defined(QT_THREAD_SUPPORT)
+ if (locker.mutex()) locker.mutex()->unlock();
+#endif
processX11Events();
-
}
-
+ else {
#if defined(QT_THREAD_SUPPORT)
- locker.mutex()->unlock();
+ if (locker.mutex()) locker.mutex()->unlock();
#endif
+ }
if (d->singletoolkit) {
return TRUE; // Eat the event
@@ -617,21 +626,27 @@ bool QEventLoop::gsourceDispatch(GSource *gs) {
bool QEventLoop::hasPendingEvents() const
{
- extern uint qGlobalPostedEventsCount(); // from qapplication.cpp
- return ( qGlobalPostedEventsCount() || ( qt_is_gui_used ? XPending( QPaintDevice::x11AppDisplay() ) : 0));
+ extern uint qGlobalPostedEventsCount(); // from qapplication.cpp
+ return ( qGlobalPostedEventsCount() || ( (qt_is_gui_used && QApplication::isGuiThread()) ? XPending( QPaintDevice::x11AppDisplay() ) : 0));
}
void QEventLoop::appStartingUp()
{
- if ( qt_is_gui_used )
- d->xfd = XConnectionNumber( QPaintDevice::x11AppDisplay() );
+ if ( qt_is_gui_used ) {
+ d->xfd = XConnectionNumber( QPaintDevice::x11AppDisplay() );
+ if ( (d->x_gPollFD.fd == -1) && QApplication::isGuiThread() ) {
+ d->x_gPollFD.fd = d->xfd;
+ d->x_gPollFD.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+ g_source_add_poll(d->gSource, &d->x_gPollFD);
+ }
+ }
}
void QEventLoop::appClosingDown()
{
- d->xfd = -1;
+ d->xfd = -1;
}
void QEventLoop::setSingleToolkitEventHandling(bool enabled) {
- d->singletoolkit = enabled;
+ d->singletoolkit = enabled;
} \ No newline at end of file
diff --git a/src/kernel/qimage.cpp b/src/kernel/qimage.cpp
index b55a0e7..214fc85 100644
--- a/src/kernel/qimage.cpp
+++ b/src/kernel/qimage.cpp
@@ -5424,6 +5424,7 @@ static void write_pbm_image( QImageIO *iio )
class QImageIOFrameGrabber : public QImageConsumer {
public:
QImageIOFrameGrabber() : framecount(0) { }
+ virtual ~QImageIOFrameGrabber() { }
QImageDecoder *decoder;
int framecount;
diff --git a/src/kernel/qinputcontext.cpp b/src/kernel/qinputcontext.cpp
index 5433ae4..3b2d476 100644
--- a/src/kernel/qinputcontext.cpp
+++ b/src/kernel/qinputcontext.cpp
@@ -477,6 +477,7 @@ bool QInputContext::isComposing() const
*/
bool QInputContext::filterEvent( const QEvent *event )
{
+ Q_UNUSED(event);
return FALSE;
}
@@ -679,6 +680,11 @@ void QInputContext::unsetFocus()
*/
void QInputContext::setMicroFocus( int x, int y, int w, int h, QFont *f )
{
+ Q_UNUSED(x);
+ Q_UNUSED(y);
+ Q_UNUSED(w);
+ Q_UNUSED(h);
+ Q_UNUSED(f);
}
@@ -705,6 +711,9 @@ void QInputContext::mouseHandler( int x, QEvent::Type type,
Qt::ButtonState button,
Qt::ButtonState state )
{
+ Q_UNUSED(x);
+ Q_UNUSED(button);
+ Q_UNUSED(state);
// Default behavior for simple ephemeral input contexts. Some
// complex input contexts should not be reset here.
if ( type == QEvent::MouseButtonPress ||
diff --git a/src/kernel/qinputcontext_x11.cpp b/src/kernel/qinputcontext_x11.cpp
index 8bdfa5e..e7c82c1 100644
--- a/src/kernel/qinputcontext_x11.cpp
+++ b/src/kernel/qinputcontext_x11.cpp
@@ -67,6 +67,8 @@
*/
bool QInputContext::x11FilterEvent( QWidget *keywidget, XEvent *event )
{
+ Q_UNUSED(keywidget);
+ Q_UNUSED(event);
return FALSE;
}
diff --git a/src/kernel/qjpegio.cpp b/src/kernel/qjpegio.cpp
index 5d2a1b1..bdb4c27 100644
--- a/src/kernel/qjpegio.cpp
+++ b/src/kernel/qjpegio.cpp
@@ -80,7 +80,7 @@ void my_error_exit (j_common_ptr cinfo)
my_error_mgr* myerr = (my_error_mgr*) cinfo->err;
char buffer[JMSG_LENGTH_MAX];
(*cinfo->err->format_message)(cinfo, buffer);
- qWarning(buffer);
+ qWarning("%s", buffer);
longjmp(myerr->setjmp_buffer, 1);
}
diff --git a/src/kernel/qnetworkprotocol.cpp b/src/kernel/qnetworkprotocol.cpp
index 4173584..e6c4a6a 100644
--- a/src/kernel/qnetworkprotocol.cpp
+++ b/src/kernel/qnetworkprotocol.cpp
@@ -381,6 +381,14 @@ public:
of these values.
*/
+QNetworkProtocolFactoryBase::QNetworkProtocolFactoryBase() {
+ //
+}
+
+QNetworkProtocolFactoryBase::~QNetworkProtocolFactoryBase() {
+ //
+}
+
/*!
Constructor of the network protocol base class. Does some
initialization and connecting of signals and slots.
diff --git a/src/kernel/qnetworkprotocol.h b/src/kernel/qnetworkprotocol.h
index 096a9ad..fa350e3 100644
--- a/src/kernel/qnetworkprotocol.h
+++ b/src/kernel/qnetworkprotocol.h
@@ -64,6 +64,10 @@ template <class T> class QValueList;
class Q_EXPORT QNetworkProtocolFactoryBase
{
public:
+ QNetworkProtocolFactoryBase();
+ virtual ~QNetworkProtocolFactoryBase();
+
+public:
virtual QNetworkProtocol *createObject() = 0;
};
diff --git a/src/kernel/qobject.cpp b/src/kernel/qobject.cpp
index 7e01dec..13486f4 100644
--- a/src/kernel/qobject.cpp
+++ b/src/kernel/qobject.cpp
@@ -50,22 +50,107 @@
#include "qptrvector.h"
#ifdef QT_THREAD_SUPPORT
-#include <qmutex.h>
+#include "qmutex.h"
#include <private/qmutexpool_p.h>
+#include "qthread.h"
#endif
#include <ctype.h>
-
+#include <stdlib.h>
#ifndef QT_NO_USERDATA
class QObjectPrivate : public QPtrVector<QObjectUserData>
+#else
+class QObjectPrivate {
+#endif
{
public:
+#ifndef QT_NO_USERDATA
QObjectPrivate( uint s ) : QPtrVector<QObjectUserData>(s){ setAutoDelete( TRUE ); }
+#endif
+ QThread* ownThread;
};
-#else
-class QObjectPrivate {
+
+#if defined(QT_THREAD_SUPPORT)
+
+void QObject::moveToThread_helper(QThread *targetThread)
+{
+ QEvent e(QEvent::ThreadChange);
+ QApplication::sendEvent(this, &e);
+
+ if (childObjects) {
+ QObject *child;
+ QObjectListIt it(*childObjects);
+ while ( (child=it.current()) ) {
+ ++it;
+ child->moveToThread_helper(targetThread);
+ }
+ }
+}
+
+void QObject::setThreadObject_helper(QThread *targetThread)
+{
+ d->ownThread = targetThread;
+
+ if (childObjects) {
+ QObject *child;
+ QObjectListIt it(*childObjects);
+ while ( (child=it.current()) ) {
+ ++it;
+ child->moveToThread_helper(targetThread);
+ }
+ }
+}
+
+/*!
+ Changes the thread affinity for this object and its children. The
+ object cannot be moved if it has a parent. Event processing will
+ continue in the \a targetThread. To move an object to the main
+ thread, pass QApplication::guiThread() as the \a targetThread.
+
+ Note that all active timers for the object will be reset. The
+ timers are first stopped in the current thread and restarted (with
+ the same interval) in the \a targetThread. As a result, constantly
+ moving an object between threads can postpone timer events
+ indefinitely.
+
+ \sa contextThreadObject()
+ */
+void QObject::moveToThread(QThread *targetThread)
+{
+ QMutexLocker locker( QApplication::qt_mutex );
+
+ if (parentObj) {
+#if defined(QT_DEBUG)
+ qWarning( "QObject::moveToThread: Cannot move objects with a parent" );
+#endif
+ return;
+ }
+ if (isWidget) {
+#if defined(QT_DEBUG)
+ qWarning( "QObject::moveToThread: Widgets cannot be moved to a new thread" );
+#endif
+ return;
+ }
+
+ QThread *objectThread = contextThreadObject();
+ QThread *currentThread = QThread::currentThreadObject();
+
+ if (objectThread != currentThread) {
+#if defined(QT_DEBUG)
+ qWarning( "QObject::moveToThread: Current thread is not the object's thread" );
+#endif
+ return;
+ }
+
+ if (objectThread == targetThread) {
+ return;
+ }
+
+ moveToThread_helper(targetThread);
+ setThreadObject_helper(targetThread);
}
+
#endif
class QSenderObjectList : public QObjectList, public QShared
@@ -75,6 +160,41 @@ public:
QObject *currentSender;
};
+class Q_EXPORT QMetaCallEvent : public QEvent
+{
+public:
+ enum MetaCallType {
+ MetaCallEmit = 0,
+ MetaCallInvoke = 1
+ };
+
+public:
+ QMetaCallEvent(int id, QObject *sender, QUObject *data, MetaCallType type);
+ ~QMetaCallEvent();
+
+ inline int id() const { return id_; }
+ inline QObject *sender() const { return sender_; }
+ inline QUObject *data() const { return data_; }
+ inline MetaCallType type() const { return type_; }
+
+private:
+ const int id_;
+ QObject *sender_;
+ QUObject *data_;
+ const MetaCallType type_;
+};
+
+/*! \internal
+ */
+QMetaCallEvent::QMetaCallEvent(int id, QObject *sender, QUObject *data, MetaCallType type)
+ :QEvent(MetaCall), id_(id), sender_(sender), data_(data), type_(type)
+{ }
+
+/*! \internal
+ */
+QMetaCallEvent::~QMetaCallEvent()
+{ }
+
/*!
\class Qt qnamespace.h
@@ -269,7 +389,21 @@ void *qt_find_obj_child( QObject *parent, const char *type, const char *name )
return 0;
}
+#ifdef QT_THREAD_SUPPORT
+/*!
+ Returns a pointer to the QThread* associated with
+ the current thread affinity of this object.
+
+ \sa moveToThread()
+ */
+
+QThread* QObject::contextThreadObject() const
+{
+ return d->ownThread;
+}
+
+#endif
#ifndef QT_NO_PRELIMINARY_SIGNAL_SPY
/*
@@ -436,6 +570,11 @@ QObject::QObject( QObject *parent, const char *name )
insert_tree( this );
isTree = TRUE;
}
+
+ if ( !d )
+ d = new QObjectPrivate(0);
+
+ d->ownThread = QThread::currentThreadObject();
}
@@ -720,6 +859,36 @@ QObject* QObject::child( const char *objName, const char *inheritsClass,
return obj;
}
+/*! \internal */
+QUObject* deepCopyQUObjectArray(QUObject* origArray)
+{
+ QUObject* newArray;
+ int count = 0;
+ while (!((origArray+count)->isLastObject)) {
+ count++;
+ }
+ count++;
+ newArray = (QUObject*)malloc(sizeof(QUObject)*count);
+ for (int i=0; i<count; i++) {
+ (origArray+i)->deepCopy(newArray+i);
+ }
+ return newArray;
+}
+
+/*! \internal */
+void destroyDeepCopiedQUObjectArray(QUObject* uArray)
+{
+ int count = 0;
+ while (!((uArray+count)->isLastObject)) {
+ count++;
+ }
+ count++;
+ for (int i=0; i<count; i++) {
+ (uArray+i)->~QUObject();
+ }
+ free(uArray);
+}
+
/*!
\fn bool QObject::isWidgetType() const
@@ -777,6 +946,40 @@ bool QObject::event( QEvent *e )
delete this;
return TRUE;
+ case QEvent::MetaCall:
+ {
+ QMetaCallEvent* metaEvent = dynamic_cast<QMetaCallEvent*>(e);
+ if (metaEvent) {
+ if (d->ownThread == QThread::currentThreadObject()) {
+ QSenderObjectList* sol;
+ QObject* oldSender = 0;
+ sol = senderObjects;
+ if ( sol ) {
+ oldSender = sol->currentSender;
+ sol->ref();
+ sol->currentSender = metaEvent->sender();
+ }
+ QUObject *o = metaEvent->data();
+ if (metaEvent->type() == QMetaCallEvent::MetaCallEmit) {
+ qt_emit( metaEvent->id(), o );
+ }
+ if (metaEvent->type() == QMetaCallEvent::MetaCallInvoke) {
+ qt_invoke( metaEvent->id(), o );
+ }
+ if (sol ) {
+ sol->currentSender = oldSender;
+ if ( sol->deref() ) {
+ delete sol;
+ }
+ }
+ }
+ else {
+ qWarning("QObject: Ignoring metacall event from non-owning thread");
+ }
+ destroyDeepCopiedQUObjectArray(metaEvent->data());
+ }
+ }
+
default:
if ( e->type() >= QEvent::User ) {
customEvent( (QCustomEvent*) e );
@@ -2337,6 +2540,7 @@ void QObject::activate_signal( int signal )
if ( !signalsBlocked() && signal >= 0 &&
( !connections || !connections->at( signal ) ) ) {
QUObject o[1];
+ o[0].isLastObject = true;
qt_spy_signal( this, signal, o );
return;
}
@@ -2349,6 +2553,7 @@ void QObject::activate_signal( int signal )
if ( !clist )
return;
QUObject o[1];
+ o[0].isLastObject = true;
activate_signal( clist, o );
}
@@ -2364,6 +2569,8 @@ void QObject::activate_signal( QConnectionList *clist, QUObject *o )
qt_spy_signal( this, connections->findRef( clist), o );
#endif
+ const QThread *currentThread = QThread::currentThreadObject();
+
QObject *object;
QSenderObjectList* sol;
QObject* oldSender = 0;
@@ -2377,10 +2584,26 @@ void QObject::activate_signal( QConnectionList *clist, QUObject *o )
sol->ref();
sol->currentSender = this;
}
- if ( c->memberType() == QSIGNAL_CODE )
- object->qt_emit( c->member(), o );
- else
- object->qt_invoke( c->member(), o );
+ if ( c->memberType() == QSIGNAL_CODE ) {
+ if (object->d->ownThread == currentThread) {
+ object->qt_emit( c->member(), o );
+ }
+ else {
+ if (object->d->ownThread && !object->d->ownThread->finished()) {
+ QApplication::postEvent(object, new QMetaCallEvent(c->member(), this, deepCopyQUObjectArray(o), QMetaCallEvent::MetaCallEmit));
+ }
+ }
+ }
+ else {
+ if (object->d->ownThread == currentThread) {
+ object->qt_invoke( c->member(), o );
+ }
+ else {
+ if (object->d->ownThread && !object->d->ownThread->finished()) {
+ QApplication::postEvent(object, new QMetaCallEvent(c->member(), this, deepCopyQUObjectArray(o), QMetaCallEvent::MetaCallInvoke));
+ }
+ }
+ }
if ( sol ) {
sol->currentSender = oldSender;
if ( sol->deref() )
@@ -2401,10 +2624,26 @@ void QObject::activate_signal( QConnectionList *clist, QUObject *o )
sol->ref();
sol->currentSender = this;
}
- if ( c->memberType() == QSIGNAL_CODE )
- object->qt_emit( c->member(), o );
- else
- object->qt_invoke( c->member(), o );
+ if ( c->memberType() == QSIGNAL_CODE ) {
+ if (object->d->ownThread == currentThread) {
+ object->qt_emit( c->member(), o );
+ }
+ else {
+ if (object->d->ownThread && !object->d->ownThread->finished()) {
+ QApplication::postEvent(object, new QMetaCallEvent(c->member(), this, deepCopyQUObjectArray(o), QMetaCallEvent::MetaCallEmit));
+ }
+ }
+ }
+ else {
+ if (object->d->ownThread == currentThread) {
+ object->qt_invoke( c->member(), o );
+ }
+ else {
+ if (object->d->ownThread && !object->d->ownThread->finished()) {
+ QApplication::postEvent(object, new QMetaCallEvent(c->member(), this, deepCopyQUObjectArray(o), QMetaCallEvent::MetaCallInvoke));
+ }
+ }
+ }
if (sol ) {
sol->currentSender = oldSender;
if ( sol->deref() )
@@ -2435,39 +2674,42 @@ void QObject::activate_signal( QConnectionList *clist, QUObject *o )
*/
#ifndef QT_NO_PRELIMINARY_SIGNAL_SPY
-#define ACTIVATE_SIGNAL_WITH_PARAM(FNAME,TYPE) \
-void QObject::FNAME( int signal, TYPE param ) \
-{ \
- if ( qt_preliminary_signal_spy ) { \
- if ( !signalsBlocked() && signal >= 0 && \
- ( !connections || !connections->at( signal ) ) ) { \
- QUObject o[2]; \
- static_QUType_##TYPE.set( o+1, param ); \
- qt_spy_signal( this, signal, o ); \
- return; \
- } \
- } \
- if ( !connections || signalsBlocked() || signal < 0 ) \
- return; \
- QConnectionList *clist = connections->at( signal ); \
- if ( !clist ) \
- return; \
- QUObject o[2]; \
- static_QUType_##TYPE.set( o+1, param ); \
- activate_signal( clist, o ); \
+#define ACTIVATE_SIGNAL_WITH_PARAM(FNAME,TYPE) \
+void QObject::FNAME( int signal, TYPE param ) \
+{ \
+ if ( qt_preliminary_signal_spy ) { \
+ if ( !signalsBlocked() && signal >= 0 && \
+ ( !connections || !connections->at( signal ) ) ) { \
+ QUObject o[2]; \
+ o[1].isLastObject = true; \
+ static_QUType_##TYPE.set( o+1, param ); \
+ qt_spy_signal( this, signal, o ); \
+ return; \
+ } \
+ } \
+ if ( !connections || signalsBlocked() || signal < 0 ) \
+ return; \
+ QConnectionList *clist = connections->at( signal ); \
+ if ( !clist ) \
+ return; \
+ QUObject o[2]; \
+ o[1].isLastObject = true; \
+ static_QUType_##TYPE.set( o+1, param ); \
+ activate_signal( clist, o ); \
}
#else
-#define ACTIVATE_SIGNAL_WITH_PARAM(FNAME,TYPE) \
-void QObject::FNAME( int signal, TYPE param ) \
-{ \
- if ( !connections || signalsBlocked() || signal < 0 ) \
- return; \
- QConnectionList *clist = connections->at( signal ); \
- if ( !clist ) \
- return; \
- QUObject o[2]; \
- static_QUType_##TYPE.set( o+1, param ); \
- activate_signal( clist, o ); \
+#define ACTIVATE_SIGNAL_WITH_PARAM(FNAME,TYPE) \
+void QObject::FNAME( int signal, TYPE param ) \
+{ \
+ if ( !connections || signalsBlocked() || signal < 0 ) \
+ return; \
+ QConnectionList *clist = connections->at( signal ); \
+ if ( !clist ) \
+ return; \
+ QUObject o[2]; \
+ o[1].isLastObject = true; \
+ static_QUType_##TYPE.set( o+1, param ); \
+ activate_signal( clist, o ); \
}
#endif
diff --git a/src/kernel/qobject.h b/src/kernel/qobject.h
index 6de28db..2f469ba 100644
--- a/src/kernel/qobject.h
+++ b/src/kernel/qobject.h
@@ -63,6 +63,10 @@ class QObjectUserData;
#endif
struct QUObject;
+#ifdef QT_THREAD_SUPPORT
+class QThread;
+#endif
+
class Q_EXPORT QObject: public Qt
{
Q_OBJECT
@@ -217,6 +221,18 @@ private: // Disabled copy constructor and operator=
QObject( const QObject & );
QObject &operator=( const QObject & );
#endif
+
+public:
+#ifdef QT_THREAD_SUPPORT
+ QThread* contextThreadObject() const;
+ void moveToThread(QThread *targetThread);
+#endif
+
+private:
+#ifdef QT_THREAD_SUPPORT
+ void moveToThread_helper(QThread *targetThread);
+ void setThreadObject_helper(QThread *targetThread);
+#endif
};
diff --git a/src/kernel/qpaintdevice_x11.cpp b/src/kernel/qpaintdevice_x11.cpp
index a755c01..5941657 100644
--- a/src/kernel/qpaintdevice_x11.cpp
+++ b/src/kernel/qpaintdevice_x11.cpp
@@ -529,11 +529,16 @@ static void create_dpis()
Q_CHECK_PTR( dpisX );
Q_CHECK_PTR( dpisY );
for ( i = 0; i < screens; i++ ) {
- dpisX[ i ] = (DisplayWidth(dpy,i) * 254 + DisplayWidthMM(dpy,i)*5)
-
- / (DisplayWidthMM(dpy,i)*10);
- dpisY[ i ] = (DisplayHeight(dpy,i) * 254 + DisplayHeightMM(dpy,i)*5)
- / (DisplayHeightMM(dpy,i)*10);
+ if (DisplayWidthMM(dpy,i) < 1)
+ dpisX[ i ] = 75; // default the dpi to 75.
+ else
+ dpisX[ i ] = (DisplayWidth(dpy,i) * 254 + DisplayWidthMM(dpy,i)*5)
+ / (DisplayWidthMM(dpy,i)*10);
+ if (DisplayHeightMM(dpy,i) < 1)
+ dpisY[ i ] = 75; // default the dpi to 75.
+ else
+ dpisY[ i ] = (DisplayHeight(dpy,i) * 254 + DisplayHeightMM(dpy,i)*5)
+ / (DisplayHeightMM(dpy,i)*10);
}
}
diff --git a/src/kernel/qprocess_unix.cpp b/src/kernel/qprocess_unix.cpp
index 2a4a2fd..c6066d4 100644
--- a/src/kernel/qprocess_unix.cpp
+++ b/src/kernel/qprocess_unix.cpp
@@ -379,7 +379,9 @@ void QProcessManager::sigchldHnd( int fd )
}
char tmp;
- ::read( fd, &tmp, sizeof(tmp) );
+ if (::read( fd, &tmp, sizeof(tmp) ) < 0) {
+ qWarning( "Could not read from file descriptor" );
+ }
#if defined(QT_QPROCESS_DEBUG)
qDebug( "QProcessManager::sigchldHnd()" );
#endif
@@ -562,7 +564,9 @@ QT_SIGNAL_RETTYPE qt_C_sigchldHnd( QT_SIGNAL_ARGS )
return;
char a = 1;
- ::write( QProcessPrivate::procManager->sigchldFd[0], &a, sizeof(a) );
+ if (::write( QProcessPrivate::procManager->sigchldFd[0], &a, sizeof(a) ) < 0) {
+ qWarning( "Could not write to file descriptor" );
+ }
}
diff --git a/src/kernel/qscriptengine_x11.cpp b/src/kernel/qscriptengine_x11.cpp
index 7d2b77d..b87680b 100644
--- a/src/kernel/qscriptengine_x11.cpp
+++ b/src/kernel/qscriptengine_x11.cpp
@@ -2725,11 +2725,7 @@ static bool khmer_shape_syllable(QOpenType *openType, QShaperItem *item)
#ifndef QT_NO_XFTFREETYPE
if (openType) {
- unsigned short logClusters[16];
- for (int i = 0; i < len; ++i)
- logClusters[i] = i;
-
- uint where[16];
+ uint where[16];
for (int i = 0; i < len; ++i) {
where[i] = ~(PreSubstProperty
@@ -3236,11 +3232,7 @@ static bool myanmar_shape_syllable(QOpenType *openType, QShaperItem *item, bool
#ifndef QT_NO_XFTFREETYPE
if (openType) {
- unsigned short logClusters[32];
- for (int i = 0; i < len; ++i)
- logClusters[i] = i;
-
- uint where[32];
+ uint where[32];
for (int i = 0; i < len; ++i) {
where[i] = ~(PreSubstProperty
diff --git a/src/kernel/qstyle.h b/src/kernel/qstyle.h
index cf7a235..0efc386 100644
--- a/src/kernel/qstyle.h
+++ b/src/kernel/qstyle.h
@@ -290,6 +290,7 @@ class Q_EXPORT QStyleControlElementData {
QString caption;
QStyleControlElementGenericWidgetData topLevelWidgetData;
Q_UINT32 topLevelWidgetFlags;
+ QPixmap paletteBgPixmap;
};
class Q_EXPORT QStyleWidgetActionRequestData {
@@ -1070,6 +1071,18 @@ public:
// bool - whether or not the upper two button drawing areas should be combined into one
SH_ScrollBar_CombineSubLineRegionDrawingAreas,
+ // Qt::QRgb - color of the popup menu arrow (active, menuitem enabled)
+ SH_PopupMenu_SubMenuArrowColorActiveEnabled,
+
+ // Qt::QRgb - color of the popup menu arrow (active, menuitem disabled)
+ SH_PopupMenu_SubMenuArrowColorActiveDisabled,
+
+ // Qt::QRgb - color of the popup menu arrow (inactive, menuitem enabled)
+ SH_PopupMenu_SubMenuArrowColorInactiveEnabled,
+
+ // Qt::QRgb - color of the popup menu arrow (active, menuitem disabled)
+ SH_PopupMenu_SubMenuArrowColorInactiveDisabled,
+
// do not add any values below/greater than this
SH_CustomBase = 0xf0000000
};
diff --git a/src/kernel/qthread.cpp b/src/kernel/qthread.cpp
index 1653a51..cfe8c56 100644
--- a/src/kernel/qthread.cpp
+++ b/src/kernel/qthread.cpp
@@ -41,6 +41,7 @@
#include "qplatformdefs.h"
#include "qthread.h"
+#include "qeventloop.h"
#include <private/qthreadinstance_p.h>
#ifndef QT_H
@@ -238,4 +239,20 @@ void QThread::postEvent( QObject * receiver, QEvent * event )
}
#endif
+QEventLoopThread::QEventLoopThread() : QThread()
+{
+ //
+}
+
+QEventLoopThread::~QEventLoopThread()
+{
+ //
+}
+
+void QEventLoopThread::run()
+{
+ QEventLoop* eventLoop = QApplication::eventLoop();
+ if (eventLoop) eventLoop->exec();
+}
+
#endif // QT_THREAD_SUPPORT
diff --git a/src/kernel/qthread.h b/src/kernel/qthread.h
index 160919f..0188ea6 100644
--- a/src/kernel/qthread.h
+++ b/src/kernel/qthread.h
@@ -118,11 +118,25 @@ protected:
private:
QThreadInstance * d;
friend class QThreadInstance;
+ friend class QCoreApplicationThread;
+ friend class QApplication;
+ friend class QEventLoop;
#if defined(Q_DISABLE_COPY)
QThread( const QThread & );
QThread &operator=( const QThread & );
#endif // Q_DISABLE_COPY
+
+public:
+ static QThread* currentThreadObject();
+};
+
+class Q_EXPORT QEventLoopThread : public QThread
+{
+ public:
+ QEventLoopThread();
+ ~QEventLoopThread();
+ virtual void run();
};
#endif // QT_THREAD_SUPPORT
diff --git a/src/kernel/qthread_unix.cpp b/src/kernel/qthread_unix.cpp
index e4d6625..52b070e 100644
--- a/src/kernel/qthread_unix.cpp
+++ b/src/kernel/qthread_unix.cpp
@@ -52,11 +52,6 @@ typedef pthread_mutex_t Q_MUTEX_T;
#include <sched.h>
-static QThreadInstance main_instance = {
- 0, { 0, &main_instance }, 0, 0, 1, 0, PTHREAD_COND_INITIALIZER, 0
-};
-
-
static QMutexPool *qt_thread_mutexpool = 0;
@@ -82,10 +77,20 @@ static void create_storage_key()
** QThreadInstance
*************************************************************************/
+void QThreadInstance::setCurrentThread(QThread *thread)
+{
+ pthread_once(&storage_key_once, create_storage_key);
+ pthread_setspecific(storage_key, thread);
+}
+
QThreadInstance *QThreadInstance::current()
{
+ QThreadInstance *ret = NULL;
pthread_once( &storage_key_once, create_storage_key );
- QThreadInstance *ret = (QThreadInstance *) pthread_getspecific( storage_key );
+ QThread *thread = (QThread *) pthread_getspecific( storage_key );
+ if (thread) {
+ ret = thread->d;
+ }
return ret;
}
@@ -101,6 +106,8 @@ void QThreadInstance::init(unsigned int stackSize)
pthread_cond_init(&thread_done, NULL);
thread_id = 0;
+ eventLoop = 0;
+
// threads have not been initialized yet, do it now
if (! qt_thread_mutexpool) QThread::initialize();
}
@@ -114,8 +121,8 @@ void *QThreadInstance::start( void *_arg )
{
void **arg = (void **) _arg;
- pthread_once( &storage_key_once, create_storage_key );
- pthread_setspecific( storage_key, arg[1] );
+ setCurrentThread( (QThread *) arg[0] );
+
pthread_cleanup_push( QThreadInstance::finish, arg[1] );
pthread_testcancel();
@@ -192,9 +199,6 @@ void QThread::initialize()
qt_global_mutexpool = new QMutexPool( TRUE, 73 );
if ( ! qt_thread_mutexpool )
qt_thread_mutexpool = new QMutexPool( FALSE, 127 );
-
- pthread_once( &storage_key_once, create_storage_key );
- pthread_setspecific( storage_key, &main_instance );
}
/*! \internal
@@ -206,11 +210,6 @@ void QThread::cleanup()
delete qt_thread_mutexpool;
qt_global_mutexpool = 0;
qt_thread_mutexpool = 0;
-
- QThreadInstance::finish(&main_instance);
-
- pthread_once( &storage_key_once, create_storage_key );
- pthread_setspecific( storage_key, 0 );
}
/*!
@@ -470,5 +469,20 @@ bool QThread::wait( unsigned long time )
return (ret == 0);
}
+/*!
+ Returns a pointer to the currently executing QThread. If the
+ current thread was not started using the QThread API, this
+ function returns zero.
+
+ Note that QApplication creates a QThread object to represent the
+ main thread; calling this function from main() after creating
+ QApplication will return a valid pointer.
+*/
+QThread *QThread::currentThreadObject()
+{
+ pthread_once(&storage_key_once, create_storage_key);
+ return reinterpret_cast<QThread *>(pthread_getspecific(storage_key));
+}
+
#endif // QT_THREAD_SUPPORT
diff --git a/src/kernel/qwidget.cpp b/src/kernel/qwidget.cpp
index 704681d..5ad69a0 100644
--- a/src/kernel/qwidget.cpp
+++ b/src/kernel/qwidget.cpp
@@ -56,6 +56,9 @@
#include "qstyle.h"
#include "qmetaobject.h"
#include "qguardedptr.h"
+#if defined(QT_THREAD_SUPPORT)
+#include "qthread.h"
+#endif
#if defined(QT_ACCESSIBILITY_SUPPORT)
#include "qaccessible.h"
#endif
@@ -887,6 +890,12 @@ QWidget::QWidget( QWidget *parent, const char *name, WFlags f, NFlags n )
}
#endif
+#if defined(QT_THREAD_SUPPORT) && defined(QT_CHECK_STATE)
+ if (QThread::currentThreadObject() != QApplication::guiThread()) {
+ qFatal( "QWidget: Cannot create a QWidget outside of the main GUI thread" );
+ }
+#endif
+
fstrut_dirty = 1;
isWidget = TRUE; // is a widget