From 72eba91414074b25fe9cd227a3fc6fe0dc612bf4 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sun, 9 Dec 2012 16:33:47 -0600 Subject: Fix X11 fd polling initialization in glib main loop This resolves Bug 1358 --- src/kernel/qeventloop_glib_p.h | 10 ++-- src/kernel/qeventloop_x11_glib.cpp | 116 ++++++++++++++++++++----------------- 2 files changed, 70 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/kernel/qeventloop_glib_p.h b/src/kernel/qeventloop_glib_p.h index ef0e6ac..663f20e 100644 --- a/src/kernel/qeventloop_glib_p.h +++ b/src/kernel/qeventloop_glib_p.h @@ -86,6 +86,10 @@ class QEventLoopPrivate public: QEventLoopPrivate() { +#if defined(Q_WS_X11) + xfd = -1; + x_gPollFD.fd = -1; +#endif // Q_WS_X11 reset(); } @@ -106,9 +110,7 @@ public: #if defined(Q_WS_X11) int xfd; - - GPollFD x_gPollFD; - + GPollFD x_gPollFD; #endif // Q_WS_X11 int thread_pipe[2]; @@ -119,7 +121,7 @@ public: QPtrList sn_pending_list; // store flags for one iteration - uint pev_flags; + uint pev_flags; // My GSource GSource * gSource; diff --git a/src/kernel/qeventloop_x11_glib.cpp b/src/kernel/qeventloop_x11_glib.cpp index 771428b..877ff44 100644 --- a/src/kernel/qeventloop_x11_glib.cpp +++ b/src/kernel/qeventloop_x11_glib.cpp @@ -82,15 +82,32 @@ static GSourceFuncs qt_gsource_funcs = { static gboolean qt_gsource_prepare ( GSource *source, 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); + 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, @@ -205,25 +222,24 @@ void QEventLoop::init() 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; + d->gSource = (GSource*)qtGSource; // poll for X11 events if ( qt_is_gui_used && QApplication::isGuiThread() ) { d->x_gPollFD.fd = d->xfd; - d->x_gPollFD.events = G_IO_IN | G_IO_HUP; + 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); @@ -279,7 +295,7 @@ bool QEventLoop::processX11Events() ProcessEventsFlags flags = d->pev_flags; // process events from the X server XEvent event; - int nevents = 0; + int nevents = 0; #if defined(QT_THREAD_SUPPORT) QMutexLocker locker( QApplication::qt_mutex ); @@ -295,49 +311,50 @@ bool QEventLoop::processX11Events() // also flushes output buffer while ( XPending( QPaintDevice::x11AppDisplay() ) ) { if ( d->shortcut ) { - return FALSE; + 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 ) + case ButtonPress: + case ButtonRelease: + case MotionNotify: + case XKeyPress: + case XKeyRelease: + case EnterNotify: + case LeaveNotify: 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; + + case ClientMessage: + { + // from qapplication_x11.cpp + extern Atom qt_wm_protocols; + extern Atom qt_wm_take_focus; + extern Atom qt_qt_scrolldone; + + // only keep the wm_take_focus and + // qt_qt_scrolldone protocols, discard all + // other client messages + if ( event.xclient.format != 32 ) + continue; + + if ( event.xclient.message_type == qt_wm_protocols || + (Atom) event.xclient.data.l[0] == qt_wm_take_focus ) + break; + if ( event.xclient.message_type == qt_qt_scrolldone ) + break; + } + + default: break; } } nevents++; - if ( qApp->x11ProcessEvent( &event ) == 1 ) - return TRUE; + if ( qApp->x11ProcessEvent( &event ) == 1 ) { + return TRUE; + } } } } @@ -463,14 +480,9 @@ bool QEventLoop::gsourceCheck(GSource *gs) { printf("inside gsourceCheck(1)\n"); #endif - // Socketnotifier events? - QPtrList *list = &d->sn_list; - //if ( list ) { - - QSockNotGPollFD *sn = list->first(); while ( sn ) { if ( sn->gPollFD.revents ) @@ -500,10 +512,9 @@ bool QEventLoop::gsourceCheck(GSource *gs) { 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"); @@ -513,7 +524,6 @@ bool QEventLoop::gsourceCheck(GSource *gs) { } // nothing to dispatch - #ifdef DEBUG_QT_GLIBMAINLOOP printf("inside gsourceCheck(2) nothing to dispatch!\n"); #endif @@ -534,7 +544,6 @@ bool QEventLoop::gsourceDispatch(GSource *gs) { #endif int nevents=0; - ProcessEventsFlags flags = d->pev_flags; #ifdef DEBUG_QT_GLIBMAINLOOP @@ -588,12 +597,10 @@ bool QEventLoop::gsourceDispatch(GSource *gs) { //return (nevents > 0); // now process x11 events! - #ifdef DEBUG_QT_GLIBMAINLOOP printf("inside gsourceDispatch(2) hasPendingEvents=%d\n", hasPendingEvents()); #endif - if (hasPendingEvents()) { // color approx. optimization - only on X11 qt_reset_color_avail(); @@ -627,6 +634,11 @@ void QEventLoop::appStartingUp() { 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); + } } } -- cgit v1.2.1