QPA: Fix event dispatcher dependent operations in platform integration

999e5162ec3e86c9cb84c3ec95dfd0ba4b21277f breaks QPlatformIntegration
implementations that perform tasks in their constructor that rely on
the event dispatcher. For example creating a QSocketNotifier is not
possible anymore since the event dispatcher is created later on.

This is fixed by introducing an additional virtual in
QPlatformIntegration that gets called after createEventDispatcher().

Two broken platform plugins have been identified so far: eglfs is
creating socket notifiers to read events from input devices and xcb's
input context plugins may use dbus. Both are updated accordingly.

Task-number: QTBUG-33768
Change-Id: I5badb623958a52ab5314ff93dd7d60061f5df70a
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@digia.com>
This commit is contained in:
Laszlo Agocs 2013-10-02 14:20:06 +02:00 committed by The Qt Project
parent 8a383c585f
commit cf092abdfc
10 changed files with 55 additions and 9 deletions

View File

@ -479,6 +479,10 @@ void QCoreApplicationPrivate::createEventDispatcher()
#endif
}
void QCoreApplicationPrivate::eventDispatcherReady()
{
}
QThread *QCoreApplicationPrivate::theMainThread = 0;
QThread *QCoreApplicationPrivate::mainThread()
{
@ -714,6 +718,7 @@ void QCoreApplication::init()
}
d->threadData->eventDispatcher = QCoreApplicationPrivate::eventDispatcher;
d->eventDispatcherReady();
#endif
#ifndef QT_NO_LIBRARY

View File

@ -99,6 +99,7 @@ public:
bool notify_helper(QObject *, QEvent *);
virtual void createEventDispatcher();
virtual void eventDispatcherReady();
static void removePostedEvent(QEvent *);
#ifdef Q_OS_WIN
static void removePostedTimerEvent(QObject *object, int timerId);

View File

@ -1048,6 +1048,14 @@ void QGuiApplicationPrivate::createEventDispatcher()
eventDispatcher = platform_integration->createEventDispatcher();
}
void QGuiApplicationPrivate::eventDispatcherReady()
{
if (platform_integration == 0)
createPlatformIntegration();
platform_integration->initialize();
}
#if defined(QT_DEBUG) && defined(Q_OS_LINUX)
// Find out if our parent process is gdb by looking at the 'exe' symlink under /proc.
static bool runningUnderDebugger()

View File

@ -84,6 +84,7 @@ public:
void createPlatformIntegration();
void createEventDispatcher() Q_DECL_OVERRIDE;
void eventDispatcherReady() Q_DECL_OVERRIDE;
virtual void notifyLayoutDirectionChange();
virtual void notifyActiveWindowChange(QWindow *previous);

View File

@ -290,6 +290,18 @@ QPaintEngine *QPlatformIntegration::createImagePaintEngine(QPaintDevice *paintDe
return 0;
}
/*!
Performs initialization steps that depend on having an event dispatcher
available. Called after the event dispatcher has been created.
Tasks that require an event dispatcher, for example creating socket notifiers, cannot be
performed in the constructor. Instead, they should be performed here. The default
implementation does nothing.
*/
void QPlatformIntegration::initialize()
{
}
/*!
Returns the platforms input context.

View File

@ -112,6 +112,7 @@ public:
// Event dispatcher:
virtual QAbstractEventDispatcher *createEventDispatcher() const = 0;
virtual void initialize();
//Deeper window system integrations
virtual QPlatformFontDatabase *fontDatabase() const;

View File

@ -80,13 +80,8 @@ static void *eglContextForContext(QOpenGLContext *context);
QEglFSIntegration::QEglFSIntegration()
: mFontDb(new QGenericUnixFontDatabase)
, mServices(new QGenericUnixServices)
, mInputContext(0)
{
#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this);
new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this);
new QEvdevTouchScreenHandlerThread(QString() /* spec */, this);
#endif
QEglFSHooks::hooks()->platformInit();
EGLint major, minor;
@ -109,8 +104,6 @@ QEglFSIntegration::QEglFSIntegration()
mScreen = new QEglFSScreen(mDisplay);
screenAdded(mScreen);
mInputContext = QPlatformInputContextFactory::create();
}
QEglFSIntegration::~QEglFSIntegration()
@ -170,6 +163,12 @@ QAbstractEventDispatcher *QEglFSIntegration::createEventDispatcher() const
return createUnixEventDispatcher();
}
void QEglFSIntegration::initialize()
{
mInputContext = QPlatformInputContextFactory::create();
createInputHandlers();
}
QVariant QEglFSIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
{
switch (hint)
@ -309,4 +308,13 @@ EGLConfig QEglFSIntegration::chooseConfig(EGLDisplay display, const QSurfaceForm
return chooser.chooseConfig();
}
void QEglFSIntegration::createInputHandlers()
{
#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this);
new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this);
new QEvdevTouchScreenHandlerThread(QString() /* spec */, this);
#endif
}
QT_END_NAMESPACE

View File

@ -68,6 +68,7 @@ public:
QPlatformServices *services() const;
QAbstractEventDispatcher *createEventDispatcher() const;
void initialize();
QVariant styleHint(QPlatformIntegration::StyleHint hint) const;
@ -86,6 +87,8 @@ public:
QPlatformInputContext *inputContext() const { return mInputContext; }
private:
void createInputHandlers();
EGLDisplay mDisplay;
QScopedPointer<QPlatformFontDatabase> mFontDb;
QScopedPointer<QPlatformServices> mServices;

View File

@ -172,7 +172,6 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char
}
m_fontDatabase.reset(new QGenericUnixFontDatabase());
m_inputContext.reset(QPlatformInputContextFactory::create());
}
QXcbIntegration::~QXcbIntegration()
@ -292,6 +291,13 @@ QAbstractEventDispatcher *QXcbIntegration::createEventDispatcher() const
return createUnixEventDispatcher();
}
void QXcbIntegration::initialize()
{
// Perform everything that may potentially need the event dispatcher (timers, socket
// notifiers) here instead of the constructor.
m_inputContext.reset(QPlatformInputContextFactory::create());
}
void QXcbIntegration::moveToScreen(QWindow *window, int screen)
{
Q_UNUSED(window);

View File

@ -68,6 +68,7 @@ public:
bool hasCapability(Capability cap) const;
QAbstractEventDispatcher *createEventDispatcher() const;
void initialize();
void moveToScreen(QWindow *window, int screen);