diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2015-09-25 14:02:04 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2015-09-25 14:02:04 +0200 |
commit | a1ad9a74ebb3c556c5f70f7e03be68b09598ac53 (patch) | |
tree | 615a96db418219a57a745a5899e39a9ac90744ec /src/gui/kernel | |
parent | 6d78b7a0c46ea04f4bb771d960e2f7dff1362341 (diff) | |
parent | 462f355e4fb16cc7a1838fa2dda0f763eee58c84 (diff) |
Merge remote-tracking branch 'origin/5.6' into dev
Conflicts:
src/corelib/io/io.pri
src/corelib/io/qdatastream.cpp
src/corelib/io/qdatastream.h
src/network/socket/qabstractsocket.cpp
src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
src/widgets/styles/qgtkstyle.cpp
tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/qmimedatabase-cache.pro
tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/qmimedatabase-xml.pro
tests/auto/dbus/qdbusconnection/qdbusconnection.pro
tests/auto/dbus/qdbuspendingcall/tst_qdbuspendingcall.cpp
tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
Change-Id: I347549a024eb5bfa986699e0a11f96cc55c797a7
Diffstat (limited to 'src/gui/kernel')
28 files changed, 274 insertions, 133 deletions
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index c7df6107f7..26a0ab5c0f 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -171,6 +171,8 @@ QInputEvent::~QInputEvent() \fn ulong QInputEvent::timestamp() const Returns the window system's timestamp for this event. + It will normally be in milliseconds since some arbitrary point + in time, such as the time when the system was started. */ /*! \fn void QInputEvent::setTimestamp(ulong atimestamp) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 898f14f8cb..c168a2bccc 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -99,6 +99,9 @@ #elif defined(Q_OS_WIN) && !defined(Q_OS_WINCE) # include <QtCore/qt_windows.h> # include <QtCore/QLibraryInfo> +# if defined(Q_OS_WINPHONE) +# include <Objbase.h> +# endif #endif // Q_OS_WIN && !Q_OS_WINCE #include <ctype.h> @@ -450,8 +453,7 @@ static QWindowGeometrySpecification windowGeometrySpecification; \row \li Miscellaneous \li startingUp(), - closingDown(), - type(). + closingDown(). \endtable \sa QCoreApplication, QAbstractEventDispatcher, QEventLoop @@ -907,16 +909,6 @@ QWindowList QGuiApplication::topLevelWindows() return topLevelWindows; } -/*! - Returns the primary (or default) screen of the application, or null if there is none - - This will be the screen where QWindows are initially shown, unless otherwise specified. - - On some platforms, it may be null when there are actually no screens connected. - It is not possible to start a new QGuiApplication while there are no screens. - Applications which were running at the time the primary screen was removed - will stop rendering graphics until one or more screens are restored. -*/ QScreen *QGuiApplication::primaryScreen() { if (QGuiApplicationPrivate::screen_list.isEmpty()) @@ -938,7 +930,7 @@ QList<QScreen *> QGuiApplication::screens() This signal is emitted whenever a new screen \a screen has been added to the system. - \sa screens(), primaryScreen(), screenRemoved() + \sa screens(), primaryScreen, screenRemoved() */ /*! @@ -955,6 +947,23 @@ QList<QScreen *> QGuiApplication::screens() /*! + \property QGuiApplication::primaryScreen + + \brief the primary (or default) screen of the application, or null if there is none. + + This will be the screen where QWindows are initially shown, unless otherwise specified. + + On some platforms, it may be null when there are actually no screens connected. + It is not possible to start a new QGuiApplication while there are no screens. + Applications which were running at the time the primary screen was removed + will stop rendering graphics until one or more screens are restored. + + The primaryScreenChanged signal was introduced in Qt 5.6. + + \sa screens() +*/ + +/*! Returns the highest screen device pixel ratio found on the system. This is the ratio between physical pixels and device-independent pixels. @@ -1257,6 +1266,16 @@ void QGuiApplicationPrivate::init() #ifndef QT_NO_SESSIONMANAGER QString session_id; QString session_key; +# if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + wchar_t guidstr[40]; + GUID guid; + CoCreateGuid(&guid); + StringFromGUID2(guid, guidstr, 40); + session_id = QString::fromWCharArray(guidstr); + CoCreateGuid(&guid); + StringFromGUID2(guid, guidstr, 40); + session_key = QString::fromWCharArray(guidstr); +# endif #endif int j = argc ? 1 : 0; for (int i=1; i<argc; i++) { @@ -1738,7 +1757,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo // should first send a move event followed by a button changed event. Since this is not the case // with the current event, we split it in two. QWindowSystemInterfacePrivate::MouseEvent mouseButtonEvent( - e->window.data(), e->timestamp, e->type, e->localPos, e->globalPos, e->buttons, e->modifiers); + e->window.data(), e->timestamp, e->type, e->localPos, e->globalPos, e->buttons, e->modifiers, e->source); if (e->flags & QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic) mouseButtonEvent.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic; e->buttons = buttons; @@ -1834,6 +1853,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo } QGuiApplication::sendSpontaneousEvent(window, &ev); + e->eventAccepted = ev.isAccepted(); if (!e->synthetic() && !ev.isAccepted() && !frameStrut && qApp->testAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents)) { diff --git a/src/gui/kernel/qguiapplication.h b/src/gui/kernel/qguiapplication.h index 6eb26e8b06..a773122d3e 100644 --- a/src/gui/kernel/qguiapplication.h +++ b/src/gui/kernel/qguiapplication.h @@ -71,6 +71,7 @@ class Q_GUI_EXPORT QGuiApplication : public QCoreApplication Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged) Q_PROPERTY(QString platformName READ platformName STORED false) Q_PROPERTY(bool quitOnLastWindowClosed READ quitOnLastWindowClosed WRITE setQuitOnLastWindowClosed) + Q_PROPERTY(QScreen *primaryScreen READ primaryScreen NOTIFY primaryScreenChanged STORED false) public: #ifdef Q_QDOC @@ -162,6 +163,7 @@ Q_SIGNALS: void fontDatabaseChanged(); void screenAdded(QScreen *screen); void screenRemoved(QScreen *screen); + void primaryScreenChanged(QScreen *screen); void lastWindowClosed(); void focusObjectChanged(QObject *focusObject); void focusWindowChanged(QWindow *focusWindow); diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp index de586ac46c..daba9f94a1 100644 --- a/src/gui/kernel/qhighdpiscaling.cpp +++ b/src/gui/kernel/qhighdpiscaling.cpp @@ -62,10 +62,10 @@ static inline qreal initialScaleFactor() } } else { if (qEnvironmentVariableIsSet(legacyDevicePixelEnvVar)) { - qWarning() << "Warning:" << legacyDevicePixelEnvVar << "is deprecated. Instead use:"; - qWarning() << " " << autoScreenEnvVar << "to enable platform plugin controlled per-screen factors."; - qWarning() << " " << screenFactorsEnvVar << "to set per-screen factors."; - qWarning() << " " << scaleFactorEnvVar << "to set the application global scale factor."; + qWarning() << "Warning:" << legacyDevicePixelEnvVar << "is deprecated. Instead use:" << endl + << " " << autoScreenEnvVar << "to enable platform plugin controlled per-screen factors." << endl + << " " << screenFactorsEnvVar << "to set per-screen factors." << endl + << " " << scaleFactorEnvVar << "to set the application global scale factor."; int dpr = qEnvironmentVariableIntValue(legacyDevicePixelEnvVar); if (dpr > 0) diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 9e5767658f..85d05959de 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -462,8 +462,7 @@ QPlatformOpenGLContext *QOpenGLContext::shareHandle() const QOpenGLContext::QOpenGLContext(QObject *parent) : QObject(*new QOpenGLContextPrivate(), parent) { - Q_D(QOpenGLContext); - d->screen = QGuiApplication::primaryScreen(); + setScreen(QGuiApplication::primaryScreen()); } /*! @@ -499,9 +498,20 @@ void QOpenGLContext::setShareContext(QOpenGLContext *shareContext) void QOpenGLContext::setScreen(QScreen *screen) { Q_D(QOpenGLContext); + if (d->screen) + disconnect(d->screen, SIGNAL(destroyed(QObject*)), this, SLOT(_q_screenDestroyed(QObject*))); d->screen = screen; if (!d->screen) d->screen = QGuiApplication::primaryScreen(); + if (d->screen) + connect(d->screen, SIGNAL(destroyed(QObject*)), this, SLOT(_q_screenDestroyed(QObject*))); +} + +void QOpenGLContextPrivate::_q_screenDestroyed(QObject *object) +{ + Q_Q(QOpenGLContext); + if (object == static_cast<QObject *>(screen)) + q->setScreen(0); } /*! @@ -1626,4 +1636,6 @@ void QOpenGLMultiGroupSharedResource::cleanup(QOpenGLContextGroup *group, QOpenG m_groups.removeOne(group); } +#include "moc_qopenglcontext.cpp" + QT_END_NAMESPACE diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h index 85e7abfa26..841967a545 100644 --- a/src/gui/kernel/qopenglcontext.h +++ b/src/gui/kernel/qopenglcontext.h @@ -241,6 +241,8 @@ private: void setTextureFunctions(QOpenGLTextureHelper* textureFuncs); void destroy(); + + Q_PRIVATE_SLOT(d_func(), void _q_screenDestroyed(QObject *object)) }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h index f9f3ce2c5f..4a746bf12b 100644 --- a/src/gui/kernel/qopenglcontext_p.h +++ b/src/gui/kernel/qopenglcontext_p.h @@ -270,6 +270,8 @@ public: static QHash<QOpenGLContext *, bool> makeCurrentTracker; static QMutex makeCurrentTrackerMutex; #endif + + void _q_screenDestroyed(QObject *object); }; Q_GUI_EXPORT void qt_gl_set_global_share_context(QOpenGLContext *context); diff --git a/src/gui/kernel/qplatformcursor.cpp b/src/gui/kernel/qplatformcursor.cpp index 7239ac7ba4..cd43fc42fe 100644 --- a/src/gui/kernel/qplatformcursor.cpp +++ b/src/gui/kernel/qplatformcursor.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the QtOpenVG module of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage diff --git a/src/gui/kernel/qplatformcursor.h b/src/gui/kernel/qplatformcursor.h index 4f4f9cc6ae..8c788fd27b 100644 --- a/src/gui/kernel/qplatformcursor.h +++ b/src/gui/kernel/qplatformcursor.h @@ -3,7 +3,7 @@ ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the QtOpenVG module of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp index 25894fd504..f69efe0935 100644 --- a/src/gui/kernel/qplatformdialoghelper.cpp +++ b/src/gui/kernel/qplatformdialoghelper.cpp @@ -119,6 +119,8 @@ static const int buttonRoleLayouts[2][5][14] = QPlatformDialogHelper::QPlatformDialogHelper() { + qRegisterMetaType<StandardButton>(); + qRegisterMetaType<ButtonRole>(); } QPlatformDialogHelper::~QPlatformDialogHelper() @@ -651,12 +653,13 @@ void QPlatformFileDialogHelper::setOptions(const QSharedPointer<QFileDialogOptio } const char *QPlatformFileDialogHelper::filterRegExp = -"^(.*)\\(([a-zA-Z0-9_.*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$"; +"^(.*)\\(([a-zA-Z0-9_.,*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$"; // Makes a list of filters from a normal filter string "Image Files (*.png *.jpg)" QStringList QPlatformFileDialogHelper::cleanFilterList(const QString &filter) { QRegExp regexp(QString::fromLatin1(filterRegExp)); + Q_ASSERT(regexp.isValid()); QString f = filter; int i = regexp.indexIn(f); if (i >= 0) diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h index ec88770862..936dbdfa89 100644 --- a/src/gui/kernel/qplatformdialoghelper.h +++ b/src/gui/kernel/qplatformdialoghelper.h @@ -160,6 +160,11 @@ Q_SIGNALS: void reject(); }; +QT_END_NAMESPACE +Q_DECLARE_METATYPE(QPlatformDialogHelper::StandardButton) +Q_DECLARE_METATYPE(QPlatformDialogHelper::ButtonRole) +QT_BEGIN_NAMESPACE + class Q_GUI_EXPORT QColorDialogOptions { public: diff --git a/src/gui/kernel/qplatforminputcontextfactory.cpp b/src/gui/kernel/qplatforminputcontextfactory.cpp index a7660e76ae..fedf940dda 100644 --- a/src/gui/kernel/qplatforminputcontextfactory.cpp +++ b/src/gui/kernel/qplatforminputcontextfactory.cpp @@ -56,48 +56,34 @@ QStringList QPlatformInputContextFactory::keys() #endif } -QPlatformInputContext *QPlatformInputContextFactory::create(const QString& key) +QString QPlatformInputContextFactory::requested() { - QStringList paramList = key.split(QLatin1Char(':')); - const QString platform = paramList.takeFirst().toLower(); - -#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) - if (QPlatformInputContext *ret = qLoadPlugin1<QPlatformInputContext, QPlatformInputContextPlugin>(loader(), platform, paramList)) - return ret; -#endif - return 0; + QByteArray env = qgetenv("QT_IM_MODULE"); + return env.isNull() ? QString() : QString::fromLocal8Bit(env); } -QPlatformInputContext *QPlatformInputContextFactory::create() +QPlatformInputContext *QPlatformInputContextFactory::create(const QString& key) { - QPlatformInputContext *ic = 0; - - QString icString = QString::fromLatin1(qgetenv("QT_IM_MODULE")); - - if (icString == QLatin1String("none")) - return 0; - - ic = create(icString); - if (ic && ic->isValid()) - return ic; - - delete ic; - ic = 0; +#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) + if (!key.isEmpty()) { + QStringList paramList = key.split(QLatin1Char(':')); + const QString platform = paramList.takeFirst().toLower(); - QStringList k = keys(); - for (int i = 0; i < k.size(); ++i) { - if (k.at(i) == icString) - continue; - ic = create(k.at(i)); + QPlatformInputContext *ic = qLoadPlugin1<QPlatformInputContext, QPlatformInputContextPlugin> + (loader(), platform, paramList); if (ic && ic->isValid()) return ic; + delete ic; - ic = 0; } - +#endif return 0; } +QPlatformInputContext *QPlatformInputContextFactory::create() +{ + return create(requested()); +} QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatforminputcontextfactory_p.h b/src/gui/kernel/qplatforminputcontextfactory_p.h index a74c4f5f80..38f4358287 100644 --- a/src/gui/kernel/qplatforminputcontextfactory_p.h +++ b/src/gui/kernel/qplatforminputcontextfactory_p.h @@ -56,6 +56,7 @@ class Q_GUI_EXPORT QPlatformInputContextFactory { public: static QStringList keys(); + static QString requested(); static QPlatformInputContext *create(const QString &key); static QPlatformInputContext *create(); }; diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp index e935907a62..457a420148 100644 --- a/src/gui/kernel/qplatformintegration.cpp +++ b/src/gui/kernel/qplatformintegration.cpp @@ -456,6 +456,24 @@ void QPlatformIntegration::screenAdded(QPlatformScreen *ps, bool isPrimary) QGuiApplicationPrivate::screen_list.append(screen); } emit qGuiApp->screenAdded(screen); + + if (isPrimary) + emit qGuiApp->primaryScreenChanged(screen); +} + +/*! + Just removes the screen, call destroyScreen instead. + + \sa destroyScreen() +*/ + +void QPlatformIntegration::removeScreen(QScreen *screen) +{ + const bool wasPrimary = (!QGuiApplicationPrivate::screen_list.isEmpty() && QGuiApplicationPrivate::screen_list[0] == screen); + QGuiApplicationPrivate::screen_list.removeOne(screen); + + if (wasPrimary && qGuiApp && !QGuiApplicationPrivate::screen_list.isEmpty()) + emit qGuiApp->primaryScreenChanged(QGuiApplicationPrivate::screen_list[0]); } /*! @@ -469,11 +487,30 @@ void QPlatformIntegration::screenAdded(QPlatformScreen *ps, bool isPrimary) void QPlatformIntegration::destroyScreen(QPlatformScreen *screen) { QScreen *qScreen = screen->screen(); - QGuiApplicationPrivate::screen_list.removeOne(qScreen); + removeScreen(qScreen); delete qScreen; delete screen; } +/*! + Should be called whenever the primary screen changes. + + When the screen specified as primary changes, this method will notify + QGuiApplication and emit the QGuiApplication::primaryScreenChanged signal. + */ + +void QPlatformIntegration::setPrimaryScreen(QPlatformScreen *newPrimary) +{ + QScreen* newPrimaryScreen = newPrimary->screen(); + int idx = QGuiApplicationPrivate::screen_list.indexOf(newPrimaryScreen); + Q_ASSERT(idx >= 0); + if (idx == 0) + return; + + QGuiApplicationPrivate::screen_list.swap(0, idx); + emit qGuiApp->primaryScreenChanged(newPrimaryScreen); +} + QStringList QPlatformIntegration::themeNames() const { return QStringList(); diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h index 2aa502b3d2..00c50a9861 100644 --- a/src/gui/kernel/qplatformintegration.h +++ b/src/gui/kernel/qplatformintegration.h @@ -172,9 +172,13 @@ public: virtual QOpenGLContext::OpenGLModuleType openGLModuleType(); #endif virtual void setApplicationIcon(const QIcon &icon) const; + + void removeScreen(QScreen *screen); + protected: void screenAdded(QPlatformScreen *screen, bool isPrimary = false); void destroyScreen(QPlatformScreen *screen); + void setPrimaryScreen(QPlatformScreen *newPrimary); }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp index 2fb53fe16b..d1d8eba697 100644 --- a/src/gui/kernel/qplatformscreen.cpp +++ b/src/gui/kernel/qplatformscreen.cpp @@ -56,7 +56,7 @@ QPlatformScreen::~QPlatformScreen() Q_D(QPlatformScreen); if (d->screen) { qWarning("Manually deleting a QPlatformScreen. Call QPlatformIntegration::destroyScreen instead."); - QGuiApplicationPrivate::screen_list.removeOne(d->screen); + QGuiApplicationPrivate::platformIntegration()->removeScreen(d->screen); delete d->screen; } } diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp index 0430d5a4c6..ea3b75c81c 100644 --- a/src/gui/kernel/qplatformwindow.cpp +++ b/src/gui/kernel/qplatformwindow.cpp @@ -702,15 +702,20 @@ QRect QPlatformWindow::windowFrameGeometry() const a resize/move event for platforms that support it, for example to implement heightForWidth(). */ -QRectF QPlatformWindow::windowClosestAcceptableGeometry(const QRectF &nativeRect) const + +QRectF QPlatformWindow::closestAcceptableGeometry(const QWindow *qWindow, const QRectF &nativeRect) { - QWindow *qWindow = window(); const QRectF rectF = QHighDpi::fromNativePixels(nativeRect, qWindow); - const QRectF correctedGeometryF = qt_window_private(qWindow)->closestAcceptableGeometry(rectF); + const QRectF correctedGeometryF = qt_window_private(const_cast<QWindow *>(qWindow))->closestAcceptableGeometry(rectF); return !correctedGeometryF.isEmpty() && rectF != correctedGeometryF ? QHighDpi::toNativePixels(correctedGeometryF, qWindow) : nativeRect; } +QRectF QPlatformWindow::windowClosestAcceptableGeometry(const QRectF &nativeRect) const +{ + return QPlatformWindow::closestAcceptableGeometry(window(), nativeRect); +} + /*! \class QPlatformWindow \since 4.8 diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h index 1b283dbb4f..9c2817906f 100644 --- a/src/gui/kernel/qplatformwindow.h +++ b/src/gui/kernel/qplatformwindow.h @@ -140,6 +140,7 @@ public: QRect windowGeometry() const; QRect windowFrameGeometry() const; QRectF windowClosestAcceptableGeometry(const QRectF &nativeRect) const; + static QRectF closestAcceptableGeometry(const QWindow *w, const QRectF &nativeRect); protected: static QString formatWindowTitle(const QString &title, const QString &separator); diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp index 407b4ee9b6..b6b50372ae 100644 --- a/src/gui/kernel/qscreen.cpp +++ b/src/gui/kernel/qscreen.cpp @@ -698,7 +698,7 @@ Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QScreen *screen) { const QDebugStateSaver saver(debug); debug.nospace(); - debug << "QScreen(" << (void *)screen; + debug << "QScreen(" << (const void *)screen; if (screen) { debug << ", name=" << screen->name(); if (debug.verbosity() > 2) { diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp index 0ff5c36119..3e267f2e0b 100644 --- a/src/gui/kernel/qshortcutmap.cpp +++ b/src/gui/kernel/qshortcutmap.cpp @@ -386,9 +386,7 @@ QKeySequence::SequenceMatch QShortcutMap::nextState(QKeyEvent *e) result = find(e); if (result == QKeySequence::NoMatch && (e->modifiers() & Qt::KeypadModifier)) { // Try to find a match without keypad modifier - QKeyEvent event = *e; - event.setModifiers(e->modifiers() & ~Qt::KeypadModifier); - result = find(&event); + result = find(e, Qt::KeypadModifier); } if (result == QKeySequence::NoMatch && e->modifiers() & Qt::ShiftModifier) { // If Shift + Key_Backtab, also try Shift + Qt::Key_Tab @@ -441,13 +439,13 @@ bool QShortcutMap::hasShortcutForKeySequence(const QKeySequence &seq) const which can be access through matches(). \sa matches */ -QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e) +QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e, int ignoredModifiers) { Q_D(QShortcutMap); if (!d->sequences.count()) return QKeySequence::NoMatch; - createNewSequences(e, d->newEntries); + createNewSequences(e, d->newEntries, ignoredModifiers); #if defined(DEBUG_QSHORTCUTMAP) qDebug() << "Possible shortcut key sequences:" << d->newEntries; #endif @@ -549,7 +547,7 @@ void QShortcutMap::clearSequence(QVector<QKeySequence> &ksl) Alters \a seq to the new sequence state, based on the current sequence state, and the new key event \a e. */ -void QShortcutMap::createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl) +void QShortcutMap::createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl, int ignoredModifiers) { Q_D(QShortcutMap); QList<int> possibleKeys = QKeyMapper::possibleKeys(e); @@ -579,7 +577,7 @@ void QShortcutMap::createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl) curKsl.setKey(0, 2); curKsl.setKey(0, 3); } - curKsl.setKey(possibleKeys.at(pkNum), index); + curKsl.setKey(possibleKeys.at(pkNum) & ~ignoredModifiers, index); } } } diff --git a/src/gui/kernel/qshortcutmap_p.h b/src/gui/kernel/qshortcutmap_p.h index 242c021ca4..2376d27c78 100644 --- a/src/gui/kernel/qshortcutmap_p.h +++ b/src/gui/kernel/qshortcutmap_p.h @@ -88,10 +88,10 @@ private: QKeySequence::SequenceMatch state(); void dispatchEvent(QKeyEvent *e); - QKeySequence::SequenceMatch find(QKeyEvent *e); + QKeySequence::SequenceMatch find(QKeyEvent *e, int ignoredModifiers = 0); QKeySequence::SequenceMatch matches(const QKeySequence &seq1, const QKeySequence &seq2) const; QVector<const QShortcutEntry *> matches() const; - void createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl); + void createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl, int ignoredModifiers); void clearSequence(QVector<QKeySequence> &ksl); int translateModifiers(Qt::KeyboardModifiers modifiers); diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp index 6e574d82e4..b02f1dd8bd 100644 --- a/src/gui/kernel/qsimpledrag.cpp +++ b/src/gui/kernel/qsimpledrag.cpp @@ -149,7 +149,7 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e) { QPoint nativePosition = getNativeMousePos(e, o); move(nativePosition); - return true; // Eat all mouse events + return true; // Eat all mouse move events } case QEvent::MouseButtonRelease: disableEventFilter(); @@ -160,8 +160,8 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e) cancel(); } exitDndEventLoop(); - return true; // Eat all mouse events - case QEvent::MouseButtonPress: + QCoreApplication::postEvent(o, new QMouseEvent(*static_cast<QMouseEvent *>(e))); + return true; // defer mouse release events until drag event loop has returned case QEvent::MouseButtonDblClick: case QEvent::Wheel: return true; diff --git a/src/gui/kernel/qtouchdevice.cpp b/src/gui/kernel/qtouchdevice.cpp index 9d19fa4b92..266b5308a2 100644 --- a/src/gui/kernel/qtouchdevice.cpp +++ b/src/gui/kernel/qtouchdevice.cpp @@ -237,6 +237,17 @@ void QTouchDevicePrivate::registerDevice(const QTouchDevice *dev) deviceList()->append(dev); } +/*! + \internal + */ +void QTouchDevicePrivate::unregisterDevice(const QTouchDevice *dev) +{ + QMutexLocker lock(&devicesMutex); + bool wasRemoved = deviceList()->removeOne(dev); + if (wasRemoved && deviceList()->isEmpty()) + qRemovePostRoutine(cleanupDevicesList); +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug debug, const QTouchDevice *device) { diff --git a/src/gui/kernel/qtouchdevice_p.h b/src/gui/kernel/qtouchdevice_p.h index 4aff8f2f33..63b83d33ec 100644 --- a/src/gui/kernel/qtouchdevice_p.h +++ b/src/gui/kernel/qtouchdevice_p.h @@ -65,6 +65,7 @@ public: int maxTouchPoints; static void registerDevice(const QTouchDevice *dev); + static void unregisterDevice(const QTouchDevice *dev); static bool isRegistered(const QTouchDevice *dev); }; diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index e93e964c6b..89bd119564 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -2508,7 +2508,7 @@ QDebug operator<<(QDebug debug, const QWindow *window) QDebugStateSaver saver(debug); debug.nospace(); if (window) { - debug << window->metaObject()->className() << '(' << (void *)window; + debug << window->metaObject()->className() << '(' << (const void *)window; if (!window->objectName().isEmpty()) debug << ", name=" << window->objectName(); if (debug.verbosity() > 2) { diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 88cf2dac93..faa1ff8068 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -49,6 +49,7 @@ QElapsedTimer QWindowSystemInterfacePrivate::eventTime; bool QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = false; QWaitCondition QWindowSystemInterfacePrivate::eventsFlushed; QMutex QWindowSystemInterfacePrivate::flushEventMutex; +QAtomicInt QWindowSystemInterfacePrivate::eventAccepted; QWindowSystemEventHandler *QWindowSystemInterfacePrivate::eventHandler; //------------------------------------------------------------ @@ -323,18 +324,18 @@ bool QWindowSystemInterface::handleKeyEvent(QWindow *tlw, ulong timestamp, QEven return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } -void QWindowSystemInterface::handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, +bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, const QString& text, bool autorep, ushort count) { unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); - handleExtendedKeyEvent(w, time, type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, + return handleExtendedKeyEvent(w, time, type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count); } -void QWindowSystemInterface::handleExtendedKeyEvent(QWindow *tlw, ulong timestamp, QEvent::Type type, int key, +bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *tlw, ulong timestamp, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, @@ -345,7 +346,7 @@ void QWindowSystemInterface::handleExtendedKeyEvent(QWindow *tlw, ulong timestam QWindowSystemInterfacePrivate::KeyEvent * e = new QWindowSystemInterfacePrivate::KeyEvent(tlw, timestamp, type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } void QWindowSystemInterface::handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods) { @@ -441,27 +442,60 @@ void QWindowSystemInterfacePrivate::removeWindowSystemEvent(WindowSystemEvent *e windowSystemEventQueue.remove(event); } +void QWindowSystemInterfacePrivate::postWindowSystemEvent(WindowSystemEvent *ev) +{ + windowSystemEventQueue.append(ev); + QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::qt_qpa_core_dispatcher(); + if (dispatcher) + dispatcher->wakeUp(); +} + +/*! + Handles a window system event. + + By default this function posts the event on the window system event queue and + wakes the Gui event dispatcher. Qt Gui will then handle the event asynchonously + at a later point. The return value is not used in asynchronous mode and will + always be true. + + In synchronous mode Qt Gui will process the event immediately. The return value + indicates if Qt accepted the event. + + \sa flushWindowSystemEvents(), setSynchronousWindowSystemEvents() +*/ bool QWindowSystemInterfacePrivate::handleWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *ev) { bool accepted = true; if (synchronousWindowSystemEvents) { - QGuiApplicationPrivate::processWindowSystemEvent(ev); - accepted = ev->eventAccepted; - delete ev; + if (QThread::currentThread() == QGuiApplication::instance()->thread()) { + // Process the event immediately on the current thread and return the accepted state. + QGuiApplicationPrivate::processWindowSystemEvent(ev); + accepted = ev->eventAccepted; + delete ev; + } else { + // Post the event on the Qt main thread queue and flush the queue. + // This will wake up the Gui thread which will process the event. + // Return the accepted state for the last event on the queue, + // which is the event posted by this function. + postWindowSystemEvent(ev); + accepted = QWindowSystemInterface::flushWindowSystemEvents(); + } } else { - windowSystemEventQueue.append(ev); - QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::qt_qpa_core_dispatcher(); - if (dispatcher) - dispatcher->wakeUp(); + postWindowSystemEvent(ev); } return accepted; } -void QWindowSystemInterface::registerTouchDevice(QTouchDevice *device) +void QWindowSystemInterface::registerTouchDevice(const QTouchDevice *device) { QTouchDevicePrivate::registerDevice(device); } +void QWindowSystemInterface::unregisterTouchDevice(const QTouchDevice *device) +{ + QTouchDevicePrivate::unregisterDevice(device); +} + void QWindowSystemInterface::handleTouchEvent(QWindow *w, QTouchDevice *device, const QList<TouchPoint> &points, Qt::KeyboardModifiers mods) { @@ -618,26 +652,33 @@ void QWindowSystemInterface::deferredFlushWindowSystemEvents(QEventLoop::Process QWindowSystemInterfacePrivate::eventsFlushed.wakeOne(); } -void QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags) +/*! + Make Qt Gui process all events on the event queue immediately. Return the + accepted state for the last event on the queue. +*/ +bool QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags) { const int count = QWindowSystemInterfacePrivate::windowSystemEventQueue.count(); if (!count) - return; + return false; if (!QGuiApplication::instance()) { qWarning().nospace() << "QWindowSystemInterface::flushWindowSystemEvents() invoked after " "QGuiApplication destruction, discarding " << count << " events."; QWindowSystemInterfacePrivate::windowSystemEventQueue.clear(); - return; + return false; } if (QThread::currentThread() != QGuiApplication::instance()->thread()) { + // Post a FlushEvents event which will trigger a call back to + // deferredFlushWindowSystemEvents from the Gui thread. QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex); QWindowSystemInterfacePrivate::FlushEventsEvent *e = new QWindowSystemInterfacePrivate::FlushEventsEvent(flags); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + QWindowSystemInterfacePrivate::postWindowSystemEvent(e); QWindowSystemInterfacePrivate::eventsFlushed.wait(&QWindowSystemInterfacePrivate::flushEventMutex); } else { sendWindowSystemEvents(flags); } + return QWindowSystemInterfacePrivate::eventAccepted.load() > 0; } bool QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags) @@ -659,6 +700,13 @@ bool QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::ProcessEventsFla nevents++; QGuiApplicationPrivate::processWindowSystemEvent(event); } + + // Record the accepted state for the processed event + // (excluding flush events). This state can then be + // returned by flushWindowSystemEvents(). + if (event->type != QWindowSystemInterfacePrivate::FlushEvents) + QWindowSystemInterfacePrivate::eventAccepted.store(event->eventAccepted); + delete event; } @@ -858,26 +906,23 @@ Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QWindowSystemInterface::TouchPo } #endif +// The following functions are used by testlib, and need to be synchronous to avoid +// race conditions with plugins delivering native events from secondary threads. + Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods, int timestamp) { - QWindowSystemInterfacePrivate::MouseEvent e(w, timestamp, local, global, b, mods, Qt::MouseEventNotSynthesized); - QGuiApplicationPrivate::processWindowSystemEvent(&e); + bool wasSynchronous = QWindowSystemInterfacePrivate::synchronousWindowSystemEvents; + QWindowSystemInterface::setSynchronousWindowSystemEvents(true); + QWindowSystemInterface::handleMouseEvent(w, timestamp, local, global, b, mods); + QWindowSystemInterface::setSynchronousWindowSystemEvents(wasSynchronous); } Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1) { - unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed(); - - // This is special handling needed for OS X which eventually will call sendEvent(), on other platforms - // this might not be safe, e.g., on Android. See: QGuiApplicationPrivate::processKeyEvent() for - // shortcut overriding on other platforms. -#if defined(Q_OS_OSX) - if (t == QEvent::KeyPress && QWindowSystemInterface::tryHandleShortcutEvent(w, timestamp, k, mods, text)) - return; -#endif // Q_OS_OSX - - QWindowSystemInterfacePrivate::KeyEvent e(w, timestamp, t, k, mods, text, autorep, count); - QGuiApplicationPrivate::processWindowSystemEvent(&e); + bool wasSynchronous = QWindowSystemInterfacePrivate::synchronousWindowSystemEvents; + QWindowSystemInterface::setSynchronousWindowSystemEvents(true); + QWindowSystemInterface::handleKeyEvent(w, t, k, mods, text, autorep, count); + QWindowSystemInterface::setSynchronousWindowSystemEvents(wasSynchronous); } Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1) @@ -885,37 +930,37 @@ Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int return QWindowSystemInterface::tryHandleShortcutEventToObject(o, timestamp, k, mods, text, autorep, count); } -Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, QTouchDevice *device, - const QList<QTouchEvent::TouchPoint> &points, - Qt::KeyboardModifiers mods = Qt::NoModifier) +static QWindowSystemInterface::TouchPoint touchPoint(const QTouchEvent::TouchPoint& pt) { - unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed(); - - if (!points.size()) // Touch events must have at least one point - return; - - if (!QTouchDevicePrivate::isRegistered(device)) // Disallow passing bogus, non-registered devices. - return; - - QEvent::Type type; - Qt::TouchPointStates states; + QWindowSystemInterface::TouchPoint p; + p.id = pt.id(); + p.flags = pt.flags(); + p.normalPosition = pt.normalizedPos(); + p.area = pt.screenRect(); + p.pressure = pt.pressure(); + p.state = pt.state(); + p.velocity = pt.velocity(); + p.rawPositions = pt.rawScreenPositions(); + return p; +} +static QList<struct QWindowSystemInterface::TouchPoint> touchPointList(const QList<QTouchEvent::TouchPoint>& pointList) +{ + QList<struct QWindowSystemInterface::TouchPoint> newList; - QList<QTouchEvent::TouchPoint>::const_iterator point = points.constBegin(); - QList<QTouchEvent::TouchPoint>::const_iterator end = points.constEnd(); - while (point != end) { - states |= point->state(); - ++point; - } + Q_FOREACH (QTouchEvent::TouchPoint p, pointList) + newList.append(touchPoint(p)); - // Determine the event type based on the combined point states. - type = QEvent::TouchUpdate; - if (states == Qt::TouchPointPressed) - type = QEvent::TouchBegin; - else if (states == Qt::TouchPointReleased) - type = QEvent::TouchEnd; + return newList; +} - QWindowSystemInterfacePrivate::TouchEvent e(w, timestamp, type, device, points, mods); - QGuiApplicationPrivate::processWindowSystemEvent(&e); +Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, QTouchDevice *device, + const QList<QTouchEvent::TouchPoint> &points, + Qt::KeyboardModifiers mods = Qt::NoModifier) +{ + bool wasSynchronous = QWindowSystemInterfacePrivate::synchronousWindowSystemEvents; + QWindowSystemInterface::setSynchronousWindowSystemEvents(true); + QWindowSystemInterface::handleTouchEvent(w, device, touchPointList(points), mods); + QWindowSystemInterface::setSynchronousWindowSystemEvents(wasSynchronous); } QWindowSystemEventHandler::~QWindowSystemEventHandler() diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index ace1a4fe24..97bd087b53 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -98,12 +98,12 @@ public: static bool handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); static bool handleKeyEvent(QWindow *w, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); - static void handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, + static bool handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, const QString& text = QString(), bool autorep = false, ushort count = 1); - static void handleExtendedKeyEvent(QWindow *w, ulong timestamp, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, + static bool handleExtendedKeyEvent(QWindow *w, ulong timestamp, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, const QString& text = QString(), bool autorep = false, @@ -127,7 +127,8 @@ public: QVector<QPointF> rawPositions; // in screen coordinates }; - static void registerTouchDevice(QTouchDevice *device); + static void registerTouchDevice(const QTouchDevice *device); + static void unregisterTouchDevice(const QTouchDevice *device); static void handleTouchEvent(QWindow *w, QTouchDevice *device, const QList<struct TouchPoint> &points, Qt::KeyboardModifiers mods = Qt::NoModifier); static void handleTouchEvent(QWindow *w, ulong timestamp, QTouchDevice *device, @@ -213,7 +214,7 @@ public: // For event dispatcher implementations static bool sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags); static void setSynchronousWindowSystemEvents(bool enable); - static void flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents); + static bool flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents); static void deferredFlushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags); static int windowSystemEventsQueued(); }; diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index cc0ca6bf81..e48d1e965b 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -51,6 +51,7 @@ #include <QMutex> #include <QList> #include <QWaitCondition> +#include <QAtomicInt> QT_BEGIN_NAMESPACE @@ -481,6 +482,7 @@ public: static WindowSystemEvent *getNonUserInputWindowSystemEvent(); static WindowSystemEvent *peekWindowSystemEvent(EventType t); static void removeWindowSystemEvent(WindowSystemEvent *event); + static void postWindowSystemEvent(WindowSystemEvent *ev); static bool handleWindowSystemEvent(WindowSystemEvent *ev); static QElapsedTimer eventTime; @@ -488,6 +490,7 @@ public: static QWaitCondition eventsFlushed; static QMutex flushEventMutex; + static QAtomicInt eventAccepted; static QList<QTouchEvent::TouchPoint> fromNativeTouchPoints(const QList<QWindowSystemInterface::TouchPoint> &points, |