summaryrefslogtreecommitdiffstats
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/ntqapplication.h13
-rw-r--r--src/kernel/ntqevent.h2
-rw-r--r--src/kernel/ntqobject.h16
-rw-r--r--src/kernel/ntqthread.h14
-rw-r--r--src/kernel/qapplication.cpp124
-rw-r--r--src/kernel/qeventloop.cpp32
-rw-r--r--src/kernel/qeventloop_unix.cpp1
-rw-r--r--src/kernel/qeventloop_unix_glib.cpp20
-rw-r--r--src/kernel/qeventloop_x11.cpp98
-rw-r--r--src/kernel/qeventloop_x11_glib.cpp600
-rw-r--r--src/kernel/qobject.cpp328
-rw-r--r--src/kernel/qthread.cpp17
-rw-r--r--src/kernel/qthread_unix.cpp46
-rw-r--r--src/kernel/qwidget.cpp9
14 files changed, 883 insertions, 437 deletions
diff --git a/src/kernel/ntqapplication.h b/src/kernel/ntqapplication.h
index cdb7fdfc8..557658ae2 100644
--- a/src/kernel/ntqapplication.h
+++ b/src/kernel/ntqapplication.h
@@ -63,6 +63,7 @@ class TQWSDecoration;
#ifdef QT_THREAD_SUPPORT
class TQMutex;
+class TQThread;
#endif // QT_THREAD_SUPPORT
@@ -369,7 +370,9 @@ private:
#ifndef QT_NO_CURSOR
static TQCursor *app_cursor;
#endif
+#ifndef QT_THREAD_SUPPORT
static TQEventLoop* eventloop;
+#endif
static int app_tracking;
static bool is_app_running;
static bool is_app_closing;
@@ -425,6 +428,7 @@ private:
static void removePostedEvent( TQEvent * );
static void removePostedEvents( TQObject *receiver, int event_type );
+ friend class TQObject;
friend class TQWidget;
friend class TQETWidget;
friend class TQDialog;
@@ -444,6 +448,15 @@ private: // Disabled copy constructor and operator=
TQApplication( const TQApplication & );
TQApplication &operator=( const TQApplication & );
#endif
+
+private:
+ static TQEventLoop* currentEventLoop();
+
+public:
+#ifdef QT_THREAD_SUPPORT
+ static TQThread* guiThread();
+#endif
+ static bool isGuiThread();
};
inline int TQApplication::argc() const
diff --git a/src/kernel/ntqevent.h b/src/kernel/ntqevent.h
index 08dc69b6c..566575ca3 100644
--- a/src/kernel/ntqevent.h
+++ b/src/kernel/ntqevent.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/ntqobject.h b/src/kernel/ntqobject.h
index 5b64e2d01..943e8319c 100644
--- a/src/kernel/ntqobject.h
+++ b/src/kernel/ntqobject.h
@@ -63,6 +63,10 @@ class TQObjectUserData;
#endif
struct TQUObject;
+#ifdef QT_THREAD_SUPPORT
+class TQThread;
+#endif
+
class Q_EXPORT TQObject: public TQt
{
TQ_OBJECT
@@ -217,6 +221,18 @@ private: // Disabled copy constructor and operator=
TQObject( const TQObject & );
TQObject &operator=( const TQObject & );
#endif
+
+public:
+#ifdef QT_THREAD_SUPPORT
+ TQThread* contextThreadObject() const;
+ void moveToThread(TQThread *targetThread);
+#endif
+
+private:
+#ifdef QT_THREAD_SUPPORT
+ void moveToThread_helper(TQThread *targetThread);
+ void setThreadObject_helper(TQThread *targetThread);
+#endif
};
diff --git a/src/kernel/ntqthread.h b/src/kernel/ntqthread.h
index c3679fbc0..824578c20 100644
--- a/src/kernel/ntqthread.h
+++ b/src/kernel/ntqthread.h
@@ -118,11 +118,25 @@ protected:
private:
TQThreadInstance * d;
friend class TQThreadInstance;
+ friend class TQCoreApplicationThread;
+ friend class TQApplication;
+ friend class TQEventLoop;
#if defined(TQ_DISABLE_COPY)
TQThread( const TQThread & );
TQThread &operator=( const TQThread & );
#endif // TQ_DISABLE_COPY
+
+public:
+ static TQThread* currentThreadObject();
+};
+
+class Q_EXPORT TQEventLoopThread : public TQThread
+{
+ public:
+ TQEventLoopThread();
+ ~TQEventLoopThread();
+ virtual void run();
};
#endif // QT_THREAD_SUPPORT
diff --git a/src/kernel/qapplication.cpp b/src/kernel/qapplication.cpp
index a552c236c..5b57bd249 100644
--- a/src/kernel/qapplication.cpp
+++ b/src/kernel/qapplication.cpp
@@ -68,6 +68,7 @@
#if defined(QT_THREAD_SUPPORT)
# include "ntqmutex.h"
# include "ntqthread.h"
+# include <private/qthreadinstance_p.h>
#endif // QT_THREAD_SUPPORT
#include <stdlib.h>
@@ -383,7 +384,25 @@ Q_EXPORT TQt::HANDLE tqt_get_application_thread_id()
}
#endif // QT_THREAD_SUPPORT
+#ifndef QT_THREAD_SUPPORT
TQEventLoop *TQApplication::eventloop = 0; // application event loop
+#endif
+
+#ifdef QT_THREAD_SUPPORT
+TQEventLoop* TQApplication::currentEventLoop() {
+ TQThread* thread = TQThread::currentThreadObject();
+ if (thread) {
+ if (thread->d) {
+ return thread->d->eventLoop;
+ }
+ }
+ return NULL;
+}
+#else
+TQEventLoop* TQApplication::currentEventLoop() {
+ return TQApplication::eventloop;
+}
+#endif
#ifndef QT_NO_ACCEL
extern bool tqt_dispatchAccelEvent( TQWidget*, TQKeyEvent* ); // def in qaccel.cpp
@@ -516,6 +535,41 @@ TQClipboard *tqt_clipboard = 0; // global clipboard object
#endif
TQWidgetList * tqt_modal_stack=0; // stack of modal widgets
+#ifdef QT_THREAD_SUPPORT
+// thread wrapper for the main() thread
+class TQCoreApplicationThread : public TQThread
+{
+public:
+ inline TQCoreApplicationThread()
+ {
+ TQThreadInstance::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 ~TQCoreApplicationThread()
+ {
+ // avoid warning from TQThread
+ d->running = false;
+ }
+private:
+ inline void run()
+ {
+ // this function should never be called, it is implemented
+ // only so that we can instantiate the object
+ tqFatal("TQCoreApplicationThread: internal error");
+ }
+};
+
+static TQCoreApplicationThread tqt_main_thread;
+static TQThread *mainThread() { return &tqt_main_thread; }
+#else
+static TQThread* mainThread() { return TQThread::currentThread(); }
+#endif
+
// Definitions for posted events
struct TQPostEvent {
TQPostEvent( TQObject *r, TQEvent *e ): receiver( r ), event( e ) {}
@@ -818,8 +872,8 @@ void TQApplication::construct( int &argc, char **argv, Type type )
initialize( argc, argv );
if ( tqt_is_gui_used )
tqt_maxWindowRect = desktop()->rect();
- if ( eventloop )
- eventloop->appStartingUp();
+ if ( currentEventLoop() )
+ currentEventLoop()->appStartingUp();
}
/*!
@@ -874,8 +928,8 @@ TQApplication::TQApplication( Display* dpy, HANDLE visual, HANDLE colormap )
if ( tqt_is_gui_used )
tqt_maxWindowRect = desktop()->rect();
- if ( eventloop )
- eventloop->appStartingUp();
+ if ( currentEventLoop() )
+ currentEventLoop()->appStartingUp();
}
/*!
@@ -916,13 +970,26 @@ TQApplication::TQApplication(Display *dpy, int argc, char **argv,
if ( tqt_is_gui_used )
tqt_maxWindowRect = desktop()->rect();
- if ( eventloop )
- eventloop->appStartingUp();
+ if ( currentEventLoop() )
+ currentEventLoop()->appStartingUp();
}
#endif // Q_WS_X11
+#ifdef QT_THREAD_SUPPORT
+TQThread* TQApplication::guiThread() {
+ return mainThread();
+}
+
+bool TQApplication::isGuiThread() {
+ return (TQThread::currentThreadObject() == guiThread());
+}
+#else
+bool TQApplication::isGuiThread() {
+ return true;
+}
+#endif
void TQApplication::init_precmdline()
{
@@ -1030,8 +1097,8 @@ TQApplication::~TQApplication()
}
#endif
- if ( eventloop )
- eventloop->appClosingDown();
+ if ( currentEventLoop() )
+ currentEventLoop()->appClosingDown();
if ( postRList ) {
TQVFuncList::Iterator it = postRList->begin();
while ( it != postRList->end() ) { // call post routines
@@ -2698,8 +2765,20 @@ bool TQApplication::internalNotify( TQObject *receiver, TQEvent * e)
}
- if (!handled)
+ if (!handled) {
+#if defined(QT_THREAD_SUPPORT)
+ bool locked = TQApplication::tqt_mutex->locked();
+ if (locked) {
+ TQApplication::tqt_mutex->unlock();
+ }
+#endif
consumed = receiver->event( e );
+#if defined(QT_THREAD_SUPPORT)
+ if (locked) {
+ TQApplication::tqt_mutex->lock();
+ }
+#endif
+ }
e->spont = FALSE;
return consumed;
}
@@ -2793,9 +2872,10 @@ void TQApplication::processOneEvent()
*/
TQEventLoop *TQApplication::eventLoop()
{
- if ( !eventloop && !is_app_closing )
+ if ( !currentEventLoop() && !is_app_closing ) {
(void) new TQEventLoop( tqApp, "default event loop" );
- return eventloop;
+ }
+ return currentEventLoop();
}
@@ -3263,8 +3343,23 @@ void TQApplication::postEvent( TQObject *receiver, TQEvent *event )
l->append( pe );
globalPostedEvents->append( pe );
- if (eventloop)
- eventloop->wakeUp();
+#ifdef QT_THREAD_SUPPORT
+ if ( event->type() == TQEvent::MetaCall ) {
+ // Wake up the receiver thread event loop
+ TQThread* thread = receiver->contextThreadObject();
+ if (thread) {
+ if (thread->d) {
+ if (thread->d->eventLoop) {
+ thread->d->eventLoop->wakeUp();
+ }
+ }
+ }
+ return;
+ }
+#endif
+
+ if (currentEventLoop())
+ currentEventLoop()->wakeUp();
}
@@ -3326,7 +3421,8 @@ void TQApplication::sendPostedEvents( TQObject *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() == TQThread::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/qeventloop.cpp b/src/kernel/qeventloop.cpp
index 4824f5717..e13a0e92a 100644
--- a/src/kernel/qeventloop.cpp
+++ b/src/kernel/qeventloop.cpp
@@ -41,6 +41,11 @@
#include "ntqapplication.h"
#include "ntqdatetime.h"
+#ifdef QT_THREAD_SUPPORT
+# include "ntqthread.h"
+# include "qthreadinstance_p.h"
+#endif
+
/*!
\class TQEventLoop
\brief The TQEventLoop class manages the event queue.
@@ -100,15 +105,27 @@ TQEventLoop::TQEventLoop( TQObject *parent, const char *name )
: TQObject( parent, name )
{
#if defined(QT_CHECK_STATE)
- if ( TQApplication::eventloop )
- tqFatal( "TQEventLoop: there must be only one event loop object. \nConstruct it before TQApplication." );
- // for now ;)
+ if ( TQApplication::currentEventLoop() )
+ tqFatal( "TQEventLoop: there must be only one event loop object per thread. \nIf this is supposed to be the main GUI event loop, construct it before TQApplication." );
+ if (!TQThread::currentThreadObject()) {
+ tqFatal( "TQEventLoop: this object can only be used in threads constructed via TQThread." );
+ }
#endif // QT_CHECK_STATE
d = new TQEventLoopPrivate;
init();
+
+#ifdef QT_THREAD_SUPPORT
+ TQThread* thread = TQThread::currentThreadObject();
+ if (thread) {
+ if (thread->d) {
+ thread->d->eventLoop = this;
+ }
+ }
+#else
TQApplication::eventloop = this;
+#endif
}
/*!
@@ -118,7 +135,16 @@ TQEventLoop::~TQEventLoop()
{
cleanup();
delete d;
+#ifdef QT_THREAD_SUPPORT
+ TQThread* thread = TQThread::currentThreadObject();
+ if (thread) {
+ if (thread->d) {
+ thread->d->eventLoop = 0;
+ }
+ }
+#else
TQApplication::eventloop = 0;
+#endif
}
/*!
diff --git a/src/kernel/qeventloop_unix.cpp b/src/kernel/qeventloop_unix.cpp
index aa13ef8b6..ccdbb4b8d 100644
--- a/src/kernel/qeventloop_unix.cpp
+++ b/src/kernel/qeventloop_unix.cpp
@@ -40,6 +40,7 @@
#include "ntqeventloop.h"
#include "ntqapplication.h"
#include "ntqbitarray.h"
+#include "ntqmutex.h"
#include <stdlib.h>
#include <sys/types.h>
diff --git a/src/kernel/qeventloop_unix_glib.cpp b/src/kernel/qeventloop_unix_glib.cpp
index cdf9f03cb..9f89332e0 100644
--- a/src/kernel/qeventloop_unix_glib.cpp
+++ b/src/kernel/qeventloop_unix_glib.cpp
@@ -44,6 +44,7 @@
#include "ntqeventloop.h"
#include "ntqapplication.h"
#include "ntqbitarray.h"
+#include "ntqmutex.h"
#include <stdlib.h>
#include <sys/types.h>
@@ -578,17 +579,14 @@ int TQEventLoop::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;
- TQApplication::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;
+ TQApplication::sendEvent( sn->obj, &event );
+ n_act++;
+ }
}
return n_act;
diff --git a/src/kernel/qeventloop_x11.cpp b/src/kernel/qeventloop_x11.cpp
index 565427106..a2d8590f6 100644
--- a/src/kernel/qeventloop_x11.cpp
+++ b/src/kernel/qeventloop_x11.cpp
@@ -146,55 +146,57 @@ bool TQEventLoop::processEvents( ProcessEventsFlags flags )
if ( tqt_is_gui_used ) {
TQApplication::sendPostedEvents();
- // Two loops so that posted events accumulate
- while ( XPending( TQPaintDevice::x11AppDisplay() ) ) {
- // also flushes output buffer
- while ( XPending( TQPaintDevice::x11AppDisplay() ) ) {
- if ( d->shortcut ) {
- return FALSE;
- }
-
- XNextEvent( TQPaintDevice::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 tqt_wm_protocols;
- extern Atom tqt_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 == tqt_wm_protocols ||
- (Atom) event.xclient.data.l[0] == tqt_wm_take_focus )
- break;
- if ( event.xclient.message_type == qt_qt_scrolldone )
- break;
+ if (TQApplication::isGuiThread()) {
+ // Two loops so that posted events accumulate
+ while ( XPending( TQPaintDevice::x11AppDisplay() ) ) {
+ // also flushes output buffer
+ while ( XPending( TQPaintDevice::x11AppDisplay() ) ) {
+ if ( d->shortcut ) {
+ return FALSE;
+ }
+
+ XNextEvent( TQPaintDevice::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 tqt_wm_protocols;
+ extern Atom tqt_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 == tqt_wm_protocols ||
+ (Atom) event.xclient.data.l[0] == tqt_wm_take_focus )
+ break;
+ if ( event.xclient.message_type == qt_qt_scrolldone )
+ break;
+ }
+
+ default: break;
+ }
+ }
+
+ nevents++;
+ if ( tqApp->x11ProcessEvent( &event ) == 1 )
+ return TRUE;
}
-
- default: break;
- }
}
-
- nevents++;
- if ( tqApp->x11ProcessEvent( &event ) == 1 )
- return TRUE;
- }
}
}
@@ -261,7 +263,7 @@ bool TQEventLoop::processEvents( ProcessEventsFlags flags )
FD_ZERO( &d->sn_vec[2].select_fds );
}
- if ( tqt_is_gui_used ) {
+ if ( tqt_is_gui_used && TQApplication::isGuiThread() ) {
// select for events on the event socket - only on X11
FD_SET( d->xfd, &d->sn_vec[0].select_fds );
highest = TQMAX( highest, d->xfd );
diff --git a/src/kernel/qeventloop_x11_glib.cpp b/src/kernel/qeventloop_x11_glib.cpp
index 11141a3a9..bb702b821 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 "ntqeventloop.h"
#include "ntqapplication.h"
@@ -58,23 +57,21 @@
// TQt-GSource Structure and Callbacks
typedef struct {
- GSource source;
- TQEventLoop * qeventLoop;
+ GSource source;
+ TQEventLoop * qeventLoop;
} TQtGSource;
-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 TQEventLoop methods!
@@ -82,25 +79,25 @@ static GSourceFuncs qt_gsource_funcs = {
static gboolean qt_gsource_prepare ( GSource *source,
gint *timeout )
{
- TQtGSource * qtGSource;
+ TQtGSource * qtGSource;
qtGSource = (TQtGSource*) source;
- return qtGSource->qeventLoop->gsourcePrepare(source, timeout);
+ return qtGSource->qeventLoop->gsourcePrepare(source, timeout);
}
static gboolean qt_gsource_check ( GSource *source )
{
- TQtGSource * qtGSource = (TQtGSource*) source;
- return qtGSource->qeventLoop->gsourceCheck(source);
+ TQtGSource * qtGSource = (TQtGSource*) source;
+ return qtGSource->qeventLoop->gsourceCheck(source);
}
static gboolean qt_gsource_dispatch ( GSource *source,
GSourceFunc callback, gpointer user_data )
{
- Q_UNUSED(callback);
- Q_UNUSED(user_data);
-
- TQtGSource * qtGSource = (TQtGSource*) source;
- return qtGSource->qeventLoop->gsourceDispatch(source);
+ Q_UNUSED(callback);
+ Q_UNUSED(user_data);
+
+ TQtGSource * qtGSource = (TQtGSource*) source;
+ return qtGSource->qeventLoop->gsourceDispatch(source);
}
@@ -134,82 +131,84 @@ static TQVFuncList *qt_postselect_handler = 0;
void qt_install_preselect_handler( VFPTR handler )
{
- if ( !qt_preselect_handler )
- qt_preselect_handler = new TQVFuncList;
- qt_preselect_handler->append( handler );
+ if ( !qt_preselect_handler ) {
+ qt_preselect_handler = new TQVFuncList;
+ }
+ qt_preselect_handler->append( handler );
}
+
void qt_remove_preselect_handler( VFPTR handler )
{
- if ( qt_preselect_handler ) {
- TQVFuncList::Iterator it = qt_preselect_handler->find( handler );
- if ( it != qt_preselect_handler->end() )
- qt_preselect_handler->remove( it );
- }
+ if ( qt_preselect_handler ) {
+ TQVFuncList::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 TQVFuncList;
- qt_postselect_handler->prepend( handler );
+ if ( !qt_postselect_handler ) {
+ qt_postselect_handler = new TQVFuncList;
+ }
+ qt_postselect_handler->prepend( handler );
}
+
void qt_remove_postselect_handler( VFPTR handler )
{
- if ( qt_postselect_handler ) {
- TQVFuncList::Iterator it = qt_postselect_handler->find( handler );
- if ( it != qt_postselect_handler->end() )
- qt_postselect_handler->remove( it );
- }
+ if ( qt_postselect_handler ) {
+ TQVFuncList::Iterator it = qt_postselect_handler->find( handler );
+ if ( it != qt_postselect_handler->end() ) {
+ qt_postselect_handler->remove( it );
+ }
+ }
}
-
void TQEventLoop::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);
+ // 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 ( tqt_is_gui_used )
- d->xfd = XConnectionNumber( TQPaintDevice::x11AppDisplay() );
+ // intitialize the X11 parts of the event loop
+ d->xfd = -1;
+ if ( tqt_is_gui_used && TQApplication::isGuiThread() ) {
+ d->xfd = XConnectionNumber( TQPaintDevice::x11AppDisplay() );
+ }
- // new GSource
+ // new GSource
+ TQtGSource * qtGSource = (TQtGSource*) g_source_new(&qt_gsource_funcs, sizeof(TQtGSource));
- TQtGSource * qtGSource = (TQtGSource*) g_source_new(&qt_gsource_funcs,
- sizeof(TQtGSource));
-
- g_source_set_can_recurse ((GSource*)qtGSource, TRUE);
+ g_source_set_can_recurse ((GSource*)qtGSource, TRUE);
+
+ qtGSource->qeventLoop = this;
- 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 );
+
+#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 ( tqt_is_gui_used ) {
-
-
+ if ( tqt_is_gui_used && TQApplication::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);
- }
+ }
// poll thread-pipe
@@ -218,21 +217,21 @@ void TQEventLoop::init()
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 TQEventLoop::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;
+ // 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
}
@@ -240,186 +239,189 @@ void TQEventLoop::cleanup()
bool TQEventLoop::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;
- #ifdef DEBUG_QT_GLIBMAINLOOP
- printf("inside processEvents(2) looplevel=%d rval=%d\n", d->looplevel, rval );
- #endif
+ d->pev_flags = flags;
- return rval; // were events processed?
+ 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 TQEventLoop::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)
- TQMutexLocker locker( TQApplication::tqt_mutex );
+ TQMutexLocker locker( TQApplication::tqt_mutex );
#endif
- // handle gui and posted events
- if ( tqt_is_gui_used ) {
- TQApplication::sendPostedEvents();
-
- // Two loops so that posted events accumulate
- while ( XPending( TQPaintDevice::x11AppDisplay() ) ) {
- // also flushes output buffer
- while ( XPending( TQPaintDevice::x11AppDisplay() ) ) {
- if ( d->shortcut ) {
- return FALSE;
- }
-
- XNextEvent( TQPaintDevice::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 tqt_wm_protocols;
- extern Atom tqt_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 == tqt_wm_protocols ||
- (Atom) event.xclient.data.l[0] == tqt_wm_take_focus )
- break;
- if ( event.xclient.message_type == qt_qt_scrolldone )
- break;
+ // handle gui and posted events
+ if ( tqt_is_gui_used ) {
+ TQApplication::sendPostedEvents();
+
+ if (TQApplication::isGuiThread()) {
+ // Two loops so that posted events accumulate
+ while ( XPending( TQPaintDevice::x11AppDisplay() ) ) {
+ // also flushes output buffer
+ while ( XPending( TQPaintDevice::x11AppDisplay() ) ) {
+ if ( d->shortcut ) {
+ return FALSE;
+ }
+
+ XNextEvent( TQPaintDevice::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 tqt_wm_protocols;
+ extern Atom tqt_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 == tqt_wm_protocols ||
+ (Atom) event.xclient.data.l[0] == tqt_wm_take_focus )
+ break;
+ if ( event.xclient.message_type == qt_qt_scrolldone )
+ break;
+ }
+
+ default: break;
+ }
+ }
+
+ nevents++;
+ if ( tqApp->x11ProcessEvent( &event ) == 1 )
+ return TRUE;
+ }
}
-
- default: break;
- }
}
-
- nevents++;
- if ( tqApp->x11ProcessEvent( &event ) == 1 )
- return TRUE;
- }
}
- }
-
- if ( d->shortcut ) {
+
+ if ( d->shortcut ) {
+ return FALSE;
+ }
+
+ TQApplication::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;
- }
-
- TQApplication::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 TQEventLoop::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)
- TQMutexLocker locker( TQApplication::tqt_mutex );
+ TQMutexLocker locker( TQApplication::tqt_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 ) ) {
- TQPtrListIterator<TQSockNotGPollFD> it( d->sn_list );
- TQSockNotGPollFD *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 {
- TQPtrListIterator<TQSockNotGPollFD> it( d->sn_list );
- TQSockNotGPollFD *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 ) ) {
+ TQPtrListIterator<TQSockNotGPollFD> it( d->sn_list );
+ TQSockNotGPollFD *sn;
+ while ( (sn=it.current()) ) {
+ ++it;
+ sn->gPollFD.events = sn->events; // restore poll events
+ }
+ }
+ else {
+ TQPtrListIterator<TQSockNotGPollFD> it( d->sn_list );
+ TQSockNotGPollFD *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 ) {
- TQVFuncList::Iterator it, end = qt_preselect_handler->end();
- for ( it = qt_preselect_handler->begin(); it != end; ++it )
- (**it)();
- }
+ if ( canWait ) {
+ emit aboutToBlock();
+ }
- // unlock the GUI mutex and select. when we return from this function, there is
- // something for us to do
+ if ( qt_preselect_handler ) {
+ TQVFuncList::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();
+ locker.mutex()->unlock();
#endif
-
- #ifdef DEBUG_QT_GLIBMAINLOOP
- printf("inside gsourcePrepare(2.1) canwait=%d\n", canWait);
- #endif
-
+
+#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
@@ -427,8 +429,8 @@ bool TQEventLoop::gsourcePrepare(GSource *gs, int * timeout)
#endif
return FALSE;
- }
-
+ }
+
// stay in poll until something happens?
if (!tm) { // fixme
*timeout = -1; // wait forever
@@ -439,25 +441,24 @@ bool TQEventLoop::gsourcePrepare(GSource *gs, int * timeout)
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
-
+#ifdef DEBUG_QT_GLIBMAINLOOP
+ printf("inside gsourcePrepare(3c) timeout=%d \n", *timeout);
+#endif
- return FALSE;
+ return FALSE;
}
bool TQEventLoop::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?
@@ -476,45 +477,45 @@ bool TQEventLoop::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
+ // nothing to dispatch
- #ifdef DEBUG_QT_GLIBMAINLOOP
- printf("inside gsourceCheck(2) nothing to dispatch!\n");
- #endif
+#ifdef DEBUG_QT_GLIBMAINLOOP
+ printf("inside gsourceCheck(2) nothing to dispatch!\n");
+#endif
- return FALSE;
+ return FALSE;
}
@@ -533,37 +534,35 @@ bool TQEventLoop::gsourceDispatch(GSource *gs) {
ProcessEventsFlags flags = d->pev_flags;
- #ifdef DEBUG_QT_GLIBMAINLOOP
- printf("inside gsourceDispatch(1)\n");
- #endif
-
- // we are awake, broadcast it
- emit awake();
- emit tqApp->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 tqApp->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 ) {
- TQVFuncList::Iterator it, end = qt_postselect_handler->end();
- for ( it = qt_postselect_handler->begin(); it != end; ++it )
- (**it)();
- }
+ if ( qt_postselect_handler ) {
+ TQVFuncList::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 ) {
-
-
TQPtrList<TQSockNotGPollFD> *list = &d->sn_list;
TQSockNotGPollFD *sn = list->first();
while ( sn ) {
@@ -572,39 +571,35 @@ bool TQEventLoop::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();
processX11Events();
-
}
#if defined(QT_THREAD_SUPPORT)
- locker.mutex()->unlock();
+ locker.mutex()->unlock();
#endif
if (d->singletoolkit) {
@@ -617,21 +612,22 @@ bool TQEventLoop::gsourceDispatch(GSource *gs) {
bool TQEventLoop::hasPendingEvents() const
{
- extern uint qGlobalPostedEventsCount(); // from qapplication.cpp
- return ( qGlobalPostedEventsCount() || ( tqt_is_gui_used ? XPending( TQPaintDevice::x11AppDisplay() ) : 0));
+ extern uint qGlobalPostedEventsCount(); // from qapplication.cpp
+ return ( qGlobalPostedEventsCount() || ( (tqt_is_gui_used && TQApplication::isGuiThread()) ? XPending( TQPaintDevice::x11AppDisplay() ) : 0));
}
void TQEventLoop::appStartingUp()
{
- if ( tqt_is_gui_used )
- d->xfd = XConnectionNumber( TQPaintDevice::x11AppDisplay() );
+ if ( tqt_is_gui_used ) {
+ d->xfd = XConnectionNumber( TQPaintDevice::x11AppDisplay() );
+ }
}
void TQEventLoop::appClosingDown()
{
- d->xfd = -1;
+ d->xfd = -1;
}
void TQEventLoop::setSingleToolkitEventHandling(bool enabled) {
- d->singletoolkit = enabled;
+ d->singletoolkit = enabled;
} \ No newline at end of file
diff --git a/src/kernel/qobject.cpp b/src/kernel/qobject.cpp
index 61ed4e7e7..3d9ef0b1c 100644
--- a/src/kernel/qobject.cpp
+++ b/src/kernel/qobject.cpp
@@ -50,22 +50,107 @@
#include "ntqptrvector.h"
#ifdef QT_THREAD_SUPPORT
-#include <ntqmutex.h>
+#include "ntqmutex.h"
#include <private/qmutexpool_p.h>
+#include "ntqthread.h"
#endif
#include <ctype.h>
-
+#include <stdlib.h>
#ifndef QT_NO_USERDATA
class TQObjectPrivate : public TQPtrVector<TQObjectUserData>
+#else
+class TQObjectPrivate {
+#endif
{
public:
+#ifndef QT_NO_USERDATA
TQObjectPrivate( uint s ) : TQPtrVector<TQObjectUserData>(s){ setAutoDelete( TRUE ); }
+#endif
+ TQThread* ownThread;
};
-#else
-class TQObjectPrivate {
+
+#if defined(QT_THREAD_SUPPORT)
+
+void TQObject::moveToThread_helper(TQThread *targetThread)
+{
+ TQEvent e(TQEvent::ThreadChange);
+ TQApplication::sendEvent(this, &e);
+
+ if (childObjects) {
+ TQObject *child;
+ TQObjectListIt it(*childObjects);
+ while ( (child=it.current()) ) {
+ ++it;
+ child->moveToThread_helper(targetThread);
+ }
+ }
+}
+
+void TQObject::setThreadObject_helper(TQThread *targetThread)
+{
+ d->ownThread = targetThread;
+
+ if (childObjects) {
+ TQObject *child;
+ TQObjectListIt 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 TQApplication::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 TQObject::moveToThread(TQThread *targetThread)
+{
+ TQMutexLocker locker( TQApplication::tqt_mutex );
+
+ if (parentObj) {
+#if defined(QT_DEBUG)
+ tqWarning( "TQObject::moveToThread: Cannot move objects with a parent" );
+#endif
+ return;
+ }
+ if (isWidget) {
+#if defined(QT_DEBUG)
+ tqWarning( "TQObject::moveToThread: Widgets cannot be moved to a new thread" );
+#endif
+ return;
+ }
+
+ TQThread *objectThread = contextThreadObject();
+ TQThread *currentThread = TQThread::currentThreadObject();
+
+ if (objectThread != currentThread) {
+#if defined(QT_DEBUG)
+ tqWarning( "TQObject::moveToThread: Current thread is not the object's thread" );
+#endif
+ return;
+ }
+
+ if (objectThread == targetThread) {
+ return;
+ }
+
+ moveToThread_helper(targetThread);
+ setThreadObject_helper(targetThread);
}
+
#endif
class TQSenderObjectList : public TQObjectList, public TQShared
@@ -75,6 +160,41 @@ public:
TQObject *currentSender;
};
+class Q_EXPORT TQMetaCallEvent : public TQEvent
+{
+public:
+ enum MetaCallType {
+ MetaCallEmit = 0,
+ MetaCallInvoke = 1
+ };
+
+public:
+ TQMetaCallEvent(int id, TQObject *sender, TQUObject *data, MetaCallType type);
+ ~TQMetaCallEvent();
+
+ inline int id() const { return id_; }
+ inline TQObject *sender() const { return sender_; }
+ inline TQUObject *data() const { return data_; }
+ inline MetaCallType type() const { return type_; }
+
+private:
+ const int id_;
+ TQObject *sender_;
+ TQUObject *data_;
+ const MetaCallType type_;
+};
+
+/*! \internal
+ */
+TQMetaCallEvent::TQMetaCallEvent(int id, TQObject *sender, TQUObject *data, MetaCallType type)
+ :TQEvent(MetaCall), id_(id), sender_(sender), data_(data), type_(type)
+{ }
+
+/*! \internal
+ */
+TQMetaCallEvent::~TQMetaCallEvent()
+{ }
+
/*!
\class TQt ntqnamespace.h
@@ -269,7 +389,21 @@ void *tqt_find_obj_child( TQObject *parent, const char *type, const char *name )
return 0;
}
+#ifdef QT_THREAD_SUPPORT
+/*!
+ Returns a pointer to the TQThread* associated with
+ the current thread affinity of this object.
+
+ \sa moveToThread()
+ */
+
+TQThread* TQObject::contextThreadObject() const
+{
+ return d->ownThread;
+}
+
+#endif
#ifndef QT_NO_PRELIMINARY_SIGNAL_SPY
/*
@@ -436,6 +570,11 @@ TQObject::TQObject( TQObject *parent, const char *name )
insert_tree( this );
isTree = TRUE;
}
+
+ if ( !d )
+ d = new TQObjectPrivate(0);
+
+ d->ownThread = TQThread::currentThreadObject();
}
@@ -720,6 +859,36 @@ TQObject* TQObject::child( const char *objName, const char *inheritsClass,
return obj;
}
+/*! \internal */
+TQUObject* deepCopyTQUObjectArray(TQUObject* origArray)
+{
+ TQUObject* newArray;
+ int count = 0;
+ while (!((origArray+count)->isLastObject)) {
+ count++;
+ }
+ count++;
+ newArray = (TQUObject*)malloc(sizeof(TQUObject)*count);
+ for (int i=0; i<count; i++) {
+ (origArray+i)->deepCopy(newArray+i);
+ }
+ return newArray;
+}
+
+/*! \internal */
+void destroyDeepCopiedTQUObjectArray(TQUObject* uArray)
+{
+ int count = 0;
+ while (!((uArray+count)->isLastObject)) {
+ count++;
+ }
+ count++;
+ for (int i=0; i<count; i++) {
+ (uArray+i)->~TQUObject();
+ }
+ free(uArray);
+}
+
/*!
\fn bool TQObject::isWidgetType() const
@@ -777,6 +946,40 @@ bool TQObject::event( TQEvent *e )
delete this;
return TRUE;
+ case TQEvent::MetaCall:
+ {
+ TQMetaCallEvent* metaEvent = dynamic_cast<TQMetaCallEvent*>(e);
+ if (metaEvent) {
+ if (d->ownThread == TQThread::currentThreadObject()) {
+ TQSenderObjectList* sol;
+ TQObject* oldSender = 0;
+ sol = senderObjects;
+ if ( sol ) {
+ oldSender = sol->currentSender;
+ sol->ref();
+ sol->currentSender = metaEvent->sender();
+ }
+ TQUObject *o = metaEvent->data();
+ if (metaEvent->type() == TQMetaCallEvent::MetaCallEmit) {
+ tqt_emit( metaEvent->id(), o );
+ }
+ if (metaEvent->type() == TQMetaCallEvent::MetaCallInvoke) {
+ tqt_invoke( metaEvent->id(), o );
+ }
+ if (sol ) {
+ sol->currentSender = oldSender;
+ if ( sol->deref() ) {
+ delete sol;
+ }
+ }
+ }
+ else {
+ tqWarning("TQObject: Ignoring metacall event from non-owning thread");
+ }
+ destroyDeepCopiedTQUObjectArray(metaEvent->data());
+ }
+ }
+
default:
if ( e->type() >= TQEvent::User ) {
customEvent( (TQCustomEvent*) e );
@@ -2337,6 +2540,7 @@ void TQObject::activate_signal( int signal )
if ( !signalsBlocked() && signal >= 0 &&
( !connections || !connections->at( signal ) ) ) {
TQUObject o[1];
+ o[0].isLastObject = true;
qt_spy_signal( this, signal, o );
return;
}
@@ -2349,6 +2553,7 @@ void TQObject::activate_signal( int signal )
if ( !clist )
return;
TQUObject o[1];
+ o[0].isLastObject = true;
activate_signal( clist, o );
}
@@ -2364,6 +2569,8 @@ void TQObject::activate_signal( TQConnectionList *clist, TQUObject *o )
qt_spy_signal( this, connections->findRef( clist), o );
#endif
+ const TQThread *currentThread = TQThread::currentThreadObject();
+
TQObject *object;
TQSenderObjectList* sol;
TQObject* oldSender = 0;
@@ -2377,10 +2584,26 @@ void TQObject::activate_signal( TQConnectionList *clist, TQUObject *o )
sol->ref();
sol->currentSender = this;
}
- if ( c->memberType() == TQSIGNAL_CODE )
- object->tqt_emit( c->member(), o );
- else
- object->tqt_invoke( c->member(), o );
+ if ( c->memberType() == TQSIGNAL_CODE ) {
+ if (object->d->ownThread == currentThread) {
+ object->tqt_emit( c->member(), o );
+ }
+ else {
+ if (object->d->ownThread && !object->d->ownThread->finished()) {
+ TQApplication::postEvent(object, new TQMetaCallEvent(c->member(), this, deepCopyTQUObjectArray(o), TQMetaCallEvent::MetaCallEmit));
+ }
+ }
+ }
+ else {
+ if (object->d->ownThread == currentThread) {
+ object->tqt_invoke( c->member(), o );
+ }
+ else {
+ if (object->d->ownThread && !object->d->ownThread->finished()) {
+ TQApplication::postEvent(object, new TQMetaCallEvent(c->member(), this, deepCopyTQUObjectArray(o), TQMetaCallEvent::MetaCallInvoke));
+ }
+ }
+ }
if ( sol ) {
sol->currentSender = oldSender;
if ( sol->deref() )
@@ -2401,10 +2624,26 @@ void TQObject::activate_signal( TQConnectionList *clist, TQUObject *o )
sol->ref();
sol->currentSender = this;
}
- if ( c->memberType() == TQSIGNAL_CODE )
- object->tqt_emit( c->member(), o );
- else
- object->tqt_invoke( c->member(), o );
+ if ( c->memberType() == TQSIGNAL_CODE ) {
+ if (object->d->ownThread == currentThread) {
+ object->tqt_emit( c->member(), o );
+ }
+ else {
+ if (object->d->ownThread && !object->d->ownThread->finished()) {
+ TQApplication::postEvent(object, new TQMetaCallEvent(c->member(), this, deepCopyTQUObjectArray(o), TQMetaCallEvent::MetaCallEmit));
+ }
+ }
+ }
+ else {
+ if (object->d->ownThread == currentThread) {
+ object->tqt_invoke( c->member(), o );
+ }
+ else {
+ if (object->d->ownThread && !object->d->ownThread->finished()) {
+ TQApplication::postEvent(object, new TQMetaCallEvent(c->member(), this, deepCopyTQUObjectArray(o), TQMetaCallEvent::MetaCallInvoke));
+ }
+ }
+ }
if (sol ) {
sol->currentSender = oldSender;
if ( sol->deref() )
@@ -2435,39 +2674,42 @@ void TQObject::activate_signal( TQConnectionList *clist, TQUObject *o )
*/
#ifndef QT_NO_PRELIMINARY_SIGNAL_SPY
-#define ACTIVATE_SIGNAL_WITH_PARAM(FNAME,TYPE) \
-void TQObject::FNAME( int signal, TYPE param ) \
-{ \
- if ( tqt_preliminary_signal_spy ) { \
- if ( !signalsBlocked() && signal >= 0 && \
- ( !connections || !connections->at( signal ) ) ) { \
- TQUObject o[2]; \
- static_QUType_##TYPE.set( o+1, param ); \
- qt_spy_signal( this, signal, o ); \
- return; \
- } \
- } \
- if ( !connections || signalsBlocked() || signal < 0 ) \
- return; \
- TQConnectionList *clist = connections->at( signal ); \
- if ( !clist ) \
- return; \
- TQUObject o[2]; \
- static_QUType_##TYPE.set( o+1, param ); \
- activate_signal( clist, o ); \
+#define ACTIVATE_SIGNAL_WITH_PARAM(FNAME,TYPE) \
+void TQObject::FNAME( int signal, TYPE param ) \
+{ \
+ if ( tqt_preliminary_signal_spy ) { \
+ if ( !signalsBlocked() && signal >= 0 && \
+ ( !connections || !connections->at( signal ) ) ) { \
+ TQUObject 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; \
+ TQConnectionList *clist = connections->at( signal ); \
+ if ( !clist ) \
+ return; \
+ TQUObject 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 TQObject::FNAME( int signal, TYPE param ) \
-{ \
- if ( !connections || signalsBlocked() || signal < 0 ) \
- return; \
- TQConnectionList *clist = connections->at( signal ); \
- if ( !clist ) \
- return; \
- TQUObject o[2]; \
- static_QUType_##TYPE.set( o+1, param ); \
- activate_signal( clist, o ); \
+#define ACTIVATE_SIGNAL_WITH_PARAM(FNAME,TYPE) \
+void TQObject::FNAME( int signal, TYPE param ) \
+{ \
+ if ( !connections || signalsBlocked() || signal < 0 ) \
+ return; \
+ TQConnectionList *clist = connections->at( signal ); \
+ if ( !clist ) \
+ return; \
+ TQUObject o[2]; \
+ o[1].isLastObject = true; \
+ static_QUType_##TYPE.set( o+1, param ); \
+ activate_signal( clist, o ); \
}
#endif
diff --git a/src/kernel/qthread.cpp b/src/kernel/qthread.cpp
index a1719313d..fe03ce066 100644
--- a/src/kernel/qthread.cpp
+++ b/src/kernel/qthread.cpp
@@ -41,6 +41,7 @@
#include "qplatformdefs.h"
#include "ntqthread.h"
+#include "ntqeventloop.h"
#include <private/qthreadinstance_p.h>
#ifndef QT_H
@@ -238,4 +239,20 @@ void TQThread::postEvent( TQObject * receiver, TQEvent * event )
}
#endif
+TQEventLoopThread::TQEventLoopThread() : TQThread()
+{
+ //
+}
+
+TQEventLoopThread::~TQEventLoopThread()
+{
+ //
+}
+
+void TQEventLoopThread::run()
+{
+ TQEventLoop* eventLoop = TQApplication::eventLoop();
+ if (eventLoop) eventLoop->exec();
+}
+
#endif // QT_THREAD_SUPPORT
diff --git a/src/kernel/qthread_unix.cpp b/src/kernel/qthread_unix.cpp
index 73319b64a..8cb39a7fc 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 TQThreadInstance main_instance = {
- 0, { 0, &main_instance }, 0, 0, 1, 0, PTHREAD_COND_INITIALIZER, 0
-};
-
-
static TQMutexPool *qt_thread_mutexpool = 0;
@@ -82,10 +77,20 @@ static void create_storage_key()
** TQThreadInstance
*************************************************************************/
+void TQThreadInstance::setCurrentThread(TQThread *thread)
+{
+ pthread_once(&storage_key_once, create_storage_key);
+ pthread_setspecific(storage_key, thread);
+}
+
TQThreadInstance *TQThreadInstance::current()
{
+ TQThreadInstance *ret = NULL;
pthread_once( &storage_key_once, create_storage_key );
- TQThreadInstance *ret = (TQThreadInstance *) pthread_getspecific( storage_key );
+ TQThread *thread = (TQThread *) pthread_getspecific( storage_key );
+ if (thread) {
+ ret = thread->d;
+ }
return ret;
}
@@ -101,6 +106,8 @@ void TQThreadInstance::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) TQThread::initialize();
}
@@ -114,8 +121,8 @@ void *TQThreadInstance::start( void *_arg )
{
void **arg = (void **) _arg;
- pthread_once( &storage_key_once, create_storage_key );
- pthread_setspecific( storage_key, arg[1] );
+ setCurrentThread( (TQThread *) arg[0] );
+
pthread_cleanup_push( TQThreadInstance::finish, arg[1] );
pthread_testcancel();
@@ -192,9 +199,6 @@ void TQThread::initialize()
tqt_global_mutexpool = new TQMutexPool( TRUE, 73 );
if ( ! qt_thread_mutexpool )
qt_thread_mutexpool = new TQMutexPool( FALSE, 127 );
-
- pthread_once( &storage_key_once, create_storage_key );
- pthread_setspecific( storage_key, &main_instance );
}
/*! \internal
@@ -206,11 +210,6 @@ void TQThread::cleanup()
delete qt_thread_mutexpool;
tqt_global_mutexpool = 0;
qt_thread_mutexpool = 0;
-
- TQThreadInstance::finish(&main_instance);
-
- pthread_once( &storage_key_once, create_storage_key );
- pthread_setspecific( storage_key, 0 );
}
/*!
@@ -470,5 +469,20 @@ bool TQThread::wait( unsigned long time )
return (ret == 0);
}
+/*!
+ Returns a pointer to the currently executing TQThread. If the
+ current thread was not started using the TQThread API, this
+ function returns zero.
+
+ Note that TQApplication creates a TQThread object to represent the
+ main thread; calling this function from main() after creating
+ TQApplication will return a valid pointer.
+*/
+TQThread *TQThread::currentThreadObject()
+{
+ pthread_once(&storage_key_once, create_storage_key);
+ return reinterpret_cast<TQThread *>(pthread_getspecific(storage_key));
+}
+
#endif // QT_THREAD_SUPPORT
diff --git a/src/kernel/qwidget.cpp b/src/kernel/qwidget.cpp
index f7ed299fb..f0ff3ed53 100644
--- a/src/kernel/qwidget.cpp
+++ b/src/kernel/qwidget.cpp
@@ -56,6 +56,9 @@
#include "ntqstyle.h"
#include "ntqmetaobject.h"
#include "ntqguardedptr.h"
+#if defined(QT_THREAD_SUPPORT)
+#include "ntqthread.h"
+#endif
#if defined(QT_ACCESSIBILITY_SUPPORT)
#include "ntqaccessible.h"
#endif
@@ -887,6 +890,12 @@ TQWidget::TQWidget( TQWidget *parent, const char *name, WFlags f, NFlags n )
}
#endif
+#if defined(QT_THREAD_SUPPORT) && defined(QT_CHECK_STATE)
+ if (TQThread::currentThreadObject() != TQApplication::guiThread()) {
+ tqFatal( "TQWidget: Cannot create a TQWidget outside of the main GUI thread" );
+ }
+#endif
+
fstrut_dirty = 1;
isWidget = TRUE; // is a widget