diff options
author | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-07-01 10:03:53 +0200 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-07-01 16:25:19 +0200 |
commit | a09a8d509a69ed16d8afbe15296b8332cacd6c66 (patch) | |
tree | 28645b437fd0390d903f753a44ba79626eecb8ac /src/plugins | |
parent | 4b28152da64f7f23a1bbb810d8cdb7626a5f0b8e (diff) | |
parent | 83f06da1c6bffff61af78cbe75a0691d53742b53 (diff) |
Merge remote-tracking branch 'origin/5.3' into dev
Conflicts:
mkspecs/qnx-x86-qcc/qplatformdefs.h
src/corelib/global/qglobal.h
src/network/socket/qnativesocketengine_winrt.cpp
src/plugins/platforms/android/androidjniaccessibility.cpp
src/plugins/platforms/windows/qwindowswindow.cpp
Manually adjusted:
mkspecs/qnx-armle-v7-qcc/qplatformdefs.h
to include 9ce697f2d54be6d94381c72af28dda79cbc027d4
Thanks goes to Sergio for the qnx mkspecs adjustments.
Change-Id: I53b1fd6bc5bc884e5ee2c2b84975f58171a1cb8e
Diffstat (limited to 'src/plugins')
62 files changed, 611 insertions, 239 deletions
diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp index b65bcdfacb..f013692809 100644 --- a/src/plugins/imageformats/ico/qicohandler.cpp +++ b/src/plugins/imageformats/ico/qicohandler.cpp @@ -517,6 +517,8 @@ void ICOReader::read16_24_32BMP(QImage & image) } } +static const char icoOrigDepthKey[] = "_q_icoOrigDepth"; + QImage ICOReader::iconAt(int index) { QImage img; @@ -535,7 +537,9 @@ QImage ICOReader::iconAt(int index) if (isPngImage) { iod->seek(iconEntry.dwImageOffset); - return QImage::fromData(iod->read(iconEntry.dwBytesInRes), "png"); + QImage image = QImage::fromData(iod->read(iconEntry.dwBytesInRes), "png"); + image.setText(QLatin1String(icoOrigDepthKey), QString::number(iconEntry.wBitCount)); + return image; } BMP_INFOHDR header; @@ -598,6 +602,7 @@ QImage ICOReader::iconAt(int index) } } } + img.setText(QLatin1String(icoOrigDepthKey), QString::number(iconEntry.wBitCount)); } } } diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp index ea0b5261c4..395bb5b090 100644 --- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp +++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp @@ -111,21 +111,17 @@ void TableGenerator::findComposeFile() } // check for the system provided compose files if (!found && cleanState()) { - QByteArray loc = locale().toUpper().toUtf8(); - QString table = readLocaleMappings(loc); - if (table.isEmpty()) - table = readLocaleMappings(readLocaleAliases(loc)); - + QString table = composeTableForLocale(); if (cleanState()) { if (table.isEmpty()) // no table mappings for the system's locale in the compose.dir m_state = UnsupportedLocale; else - found = processFile(systemComposeDir() + QLatin1String("/") + table); + found = processFile(systemComposeDir() + QLatin1Char('/') + table); #ifdef DEBUG_GENERATOR if (found) qDebug() << "Using Compose file from: " << - systemComposeDir() + QLatin1String("/") + table; + systemComposeDir() + QLatin1Char('/') + table; #endif } } @@ -137,6 +133,15 @@ void TableGenerator::findComposeFile() m_state = MissingComposeFile; } +QString TableGenerator::composeTableForLocale() +{ + QByteArray loc = locale().toUpper().toUtf8(); + QString table = readLocaleMappings(loc); + if (table.isEmpty()) + table = readLocaleMappings(readLocaleAliases(loc)); + return table; +} + bool TableGenerator::findSystemComposeDir() { bool found = false; @@ -311,7 +316,7 @@ void TableGenerator::parseIncludeInstruction(QString line) // expand substitutions if present line.replace(QLatin1String("%H"), QString(qgetenv("HOME"))); - line.replace(QLatin1String("%L"), locale()); + line.replace(QLatin1String("%L"), systemComposeDir() + QLatin1Char('/') + composeTableForLocale()); line.replace(QLatin1String("%S"), systemComposeDir()); processFile(line); diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h index 248c09f3ea..6ce89cfe77 100644 --- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h +++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h @@ -118,13 +118,14 @@ protected: void findComposeFile(); bool findSystemComposeDir(); QString systemComposeDir(); + QString composeTableForLocale(); ushort keysymToUtf8(quint32 sym); QString readLocaleMappings(const QByteArray &locale); QByteArray readLocaleAliases(const QByteArray &locale); void initPossibleLocations(); - bool cleanState() const { return ((m_state & NoErrors) == NoErrors); } + bool cleanState() const { return m_state == NoErrors; } QString locale() const; private: diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp index 7fc7595881..a7fec8748b 100644 --- a/src/plugins/platforms/android/androidjniaccessibility.cpp +++ b/src/plugins/platforms/android/androidjniaccessibility.cpp @@ -49,6 +49,7 @@ #include "qrect.h" #include "QtGui/qaccessible.h" #include <QtCore/qmath.h> +#include <QtCore/private/qjnihelpers_p.h> #include "qdebug.h" @@ -56,6 +57,8 @@ static const char m_qtTag[] = "Qt A11Y"; static const char m_classErrorMsg[] = "Can't find class \"%s\""; static const char m_methodErrorMsg[] = "Can't find method \"%s%s\""; +QT_BEGIN_NAMESPACE + namespace QtAndroidAccessibility { static jmethodID m_addActionMethodID = 0; @@ -227,7 +230,7 @@ if (!clazz) { \ if (desc.isEmpty()) desc = iface->text(QAccessible::Description); if (QAccessibleTextInterface *textIface = iface->textInterface()) { - if (textIface->selectionCount() > 0) { + if (m_setTextSelectionMethodID && textIface->selectionCount() > 0) { int startSelection; int endSelection; textIface->selection(0, &startSelection, &endSelection); @@ -286,12 +289,15 @@ if (!clazz) { \ bool registerNatives(JNIEnv *env) { + if (QtAndroidPrivate::androidSdkVersion() < 16) + return true; // We need API level 16 or higher + jclass clazz; FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/accessibility/QtNativeAccessibility"); jclass appClass = static_cast<jclass>(env->NewGlobalRef(clazz)); if (env->RegisterNatives(appClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) { - __android_log_print(ANDROID_LOG_FATAL,"Qt", "RegisterNatives failed"); + __android_log_print(ANDROID_LOG_FATAL,"Qt A11y", "RegisterNatives failed"); return false; } @@ -305,9 +311,14 @@ if (!clazz) { \ GET_AND_CHECK_STATIC_METHOD(m_setFocusableMethodID, nodeInfoClass, "setFocusable", "(Z)V"); GET_AND_CHECK_STATIC_METHOD(m_setFocusedMethodID, nodeInfoClass, "setFocused", "(Z)V"); GET_AND_CHECK_STATIC_METHOD(m_setScrollableMethodID, nodeInfoClass, "setScrollable", "(Z)V"); - GET_AND_CHECK_STATIC_METHOD(m_setTextSelectionMethodID, nodeInfoClass, "setTextSelection", "(II)V"); GET_AND_CHECK_STATIC_METHOD(m_setVisibleToUserMethodID, nodeInfoClass, "setVisibleToUser", "(Z)V"); + if (QtAndroidPrivate::androidSdkVersion() >= 18) { + GET_AND_CHECK_STATIC_METHOD(m_setTextSelectionMethodID, nodeInfoClass, "setTextSelection", "(II)V"); + } + return true; } } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/androidjniaccessibility.h b/src/plugins/platforms/android/androidjniaccessibility.h index e708138c33..3ca89242fe 100644 --- a/src/plugins/platforms/android/androidjniaccessibility.h +++ b/src/plugins/platforms/android/androidjniaccessibility.h @@ -42,10 +42,15 @@ #ifndef ANDROIDJNIACCESSIBILITY_H #define ANDROIDJNIACCESSIBILITY_H #include <jni.h> +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE namespace QtAndroidAccessibility { bool registerNatives(JNIEnv *env); } +QT_END_NAMESPACE + #endif // ANDROIDJNIINPUT_H diff --git a/src/plugins/platforms/android/androidjniclipboard.cpp b/src/plugins/platforms/android/androidjniclipboard.cpp index 05270ac374..87bb08910d 100644 --- a/src/plugins/platforms/android/androidjniclipboard.cpp +++ b/src/plugins/platforms/android/androidjniclipboard.cpp @@ -42,6 +42,8 @@ #include "androidjniclipboard.h" #include "androidjnimain.h" +QT_BEGIN_NAMESPACE + using namespace QtAndroid; namespace QtAndroidClipboard { @@ -118,3 +120,5 @@ namespace QtAndroidClipboard return true; } } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/androidjniclipboard.h b/src/plugins/platforms/android/androidjniclipboard.h index 15cd93202e..764ef908df 100644 --- a/src/plugins/platforms/android/androidjniclipboard.h +++ b/src/plugins/platforms/android/androidjniclipboard.h @@ -45,6 +45,8 @@ #include <jni.h> #include <QString> +QT_BEGIN_NAMESPACE + class QAndroidPlatformClipboard; namespace QtAndroidClipboard { @@ -58,4 +60,6 @@ namespace QtAndroidClipboard bool registerNatives(JNIEnv *env); } +QT_END_NAMESPACE + #endif // ANDROIDJNICLIPBOARD_H diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index 760da7a767..defc59abf0 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -49,6 +49,8 @@ #include <QDebug> +QT_BEGIN_NAMESPACE + using namespace QtAndroid; namespace QtAndroidInput @@ -758,3 +760,5 @@ namespace QtAndroidInput return true; } } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/androidjniinput.h b/src/plugins/platforms/android/androidjniinput.h index a78c7519db..5a7357633c 100644 --- a/src/plugins/platforms/android/androidjniinput.h +++ b/src/plugins/platforms/android/androidjniinput.h @@ -42,6 +42,9 @@ #ifndef ANDROIDJNIINPUT_H #define ANDROIDJNIINPUT_H #include <jni.h> +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE namespace QtAndroidInput { @@ -56,4 +59,6 @@ namespace QtAndroidInput bool registerNatives(JNIEnv *env); } +QT_END_NAMESPACE + #endif // ANDROIDJNIINPUT_H diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index d484a2faff..09c56f398c 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -76,6 +76,8 @@ Q_IMPORT_PLUGIN(QAndroidPlatformIntegrationPlugin) +QT_BEGIN_NAMESPACE + static JavaVM *m_javaVM = NULL; static jclass m_applicationClass = NULL; static jobject m_classLoaderObject = NULL; @@ -423,6 +425,7 @@ namespace QtAndroid m_destroySurfaceMethodID, surfaceId); } + } // namespace QtAndroid @@ -548,7 +551,7 @@ static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface, } static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/, - jint /*widthPixels*/, jint /*heightPixels*/, + jint widthPixels, jint heightPixels, jint desktopWidthPixels, jint desktopHeightPixels, jdouble xdpi, jdouble ydpi, jdouble scaledDensity) { @@ -557,13 +560,17 @@ static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/, m_scaledDensity = scaledDensity; if (!m_androidPlatformIntegration) { - QAndroidPlatformIntegration::setDefaultDisplayMetrics(desktopWidthPixels,desktopHeightPixels, - qRound(double(desktopWidthPixels) / xdpi * 25.4), - qRound(double(desktopHeightPixels) / ydpi * 25.4)); + QAndroidPlatformIntegration::setDefaultDisplayMetrics(desktopWidthPixels, + desktopHeightPixels, + qRound(double(desktopWidthPixels) / xdpi * 25.4), + qRound(double(desktopHeightPixels) / ydpi * 25.4), + widthPixels, + heightPixels); } else { m_androidPlatformIntegration->setDisplayMetrics(qRound(double(desktopWidthPixels) / xdpi * 25.4), qRound(double(desktopHeightPixels) / ydpi * 25.4)); m_androidPlatformIntegration->setDesktopSize(desktopWidthPixels, desktopHeightPixels); + m_androidPlatformIntegration->setScreenSize(widthPixels, heightPixels); } } @@ -743,17 +750,11 @@ static int registerNatives(JNIEnv *env) return JNI_TRUE; } -jint androidApiLevel(JNIEnv *env) -{ - jclass clazz; - FIND_AND_CHECK_CLASS("android/os/Build$VERSION"); - jfieldID fieldId; - GET_AND_CHECK_STATIC_FIELD(fieldId, clazz, "SDK_INT", "I"); - return env->GetStaticIntField(clazz, fieldId); -} +QT_END_NAMESPACE Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/) { + QT_USE_NAMESPACE typedef union { JNIEnv *nativeEnvironment; void *venv; @@ -774,17 +775,12 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/) || !QtAndroidInput::registerNatives(env) || !QtAndroidClipboard::registerNatives(env) || !QtAndroidMenu::registerNatives(env) + || !QtAndroidAccessibility::registerNatives(env) || !QtAndroidDialogHelpers::registerNatives(env)) { __android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed"); return -1; } - jint apiLevel = androidApiLevel(env); - if (apiLevel >= 16 && !QtAndroidAccessibility::registerNatives(env)) { - __android_log_print(ANDROID_LOG_FATAL, "Qt A11y", "registerNatives failed"); - return -1; - } - m_javaVM = vm; return JNI_VERSION_1_4; } diff --git a/src/plugins/platforms/android/androidjnimain.h b/src/plugins/platforms/android/androidjnimain.h index c00b23fff3..29896529ca 100644 --- a/src/plugins/platforms/android/androidjnimain.h +++ b/src/plugins/platforms/android/androidjnimain.h @@ -50,6 +50,8 @@ #include <QImage> +QT_BEGIN_NAMESPACE + class QRect; class QPoint; class QThread; @@ -119,4 +121,7 @@ namespace QtAndroid QString deviceName(); } + +QT_END_NAMESPACE + #endif // ANDROID_APP_H diff --git a/src/plugins/platforms/android/androidjnimenu.cpp b/src/plugins/platforms/android/androidjnimenu.cpp index dc2afe2b03..6a979b9255 100644 --- a/src/plugins/platforms/android/androidjnimenu.cpp +++ b/src/plugins/platforms/android/androidjnimenu.cpp @@ -50,6 +50,8 @@ #include <QQueue> #include <QWindow> +QT_BEGIN_NAMESPACE + using namespace QtAndroid; namespace QtAndroidMenu @@ -428,3 +430,5 @@ namespace QtAndroidMenu return true; } } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/androidjnimenu.h b/src/plugins/platforms/android/androidjnimenu.h index 7c5422f67b..2ae406901a 100644 --- a/src/plugins/platforms/android/androidjnimenu.h +++ b/src/plugins/platforms/android/androidjnimenu.h @@ -43,6 +43,9 @@ #define ANDROIDJNIMENU_H #include <jni.h> +#include <qglobal.h> + +QT_BEGIN_NAMESPACE class QAndroidPlatformMenuBar; class QAndroidPlatformMenu; @@ -66,4 +69,6 @@ namespace QtAndroidMenu bool registerNatives(JNIEnv *env); } +QT_END_NAMESPACE + #endif // ANDROIDJNIMENU_H diff --git a/src/plugins/platforms/android/androidsurfaceclient.h b/src/plugins/platforms/android/androidsurfaceclient.h index 254e47123b..94f16a8547 100644 --- a/src/plugins/platforms/android/androidsurfaceclient.h +++ b/src/plugins/platforms/android/androidsurfaceclient.h @@ -44,6 +44,8 @@ #include <QMutex> #include <jni.h> +QT_BEGIN_NAMESPACE + class AndroidSurfaceClient { public: @@ -55,4 +57,6 @@ protected: QMutex m_surfaceMutex; }; +QT_END_NAMESPACE + #endif // ANDROIDSURFACECLIENT_H diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp index 224a8ca9f7..70ea3d756f 100644 --- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp +++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp @@ -45,6 +45,8 @@ #include <QCoreApplication> #include <QVector> +QT_BEGIN_NAMESPACE + typedef QVector<QString> FilesList; struct AndroidAssetDir @@ -394,3 +396,5 @@ QAbstractFileEngine * AndroidAssetsFileEngineHandler::create(const QString &file } return 0; } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.h b/src/plugins/platforms/android/qandroidassetsfileenginehandler.h index ac16ad7b79..a48a288ebc 100644 --- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.h +++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.h @@ -49,6 +49,8 @@ #include <android/asset_manager.h> +QT_BEGIN_NAMESPACE + struct AndroidAssetDir; class AndroidAssetsFileEngineHandler: public QAbstractFileEngineHandler { @@ -67,4 +69,6 @@ private: mutable bool m_hasTriedPrepopulatingCache; }; +QT_END_NAMESPACE + #endif // QANDROIDASSETSFILEENGINEHANDLER_H diff --git a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp index 897feb5802..6e4b6d8255 100644 --- a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp +++ b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp @@ -47,6 +47,8 @@ #include <private/qguiapplication_p.h> #include <qpa/qplatformtheme.h> +QT_BEGIN_NAMESPACE + namespace QtAndroidDialogHelpers { static jclass g_messageDialogHelperClass = 0; @@ -172,3 +174,5 @@ bool registerNatives(JNIEnv *env) return true; } } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformdialoghelpers.h b/src/plugins/platforms/android/qandroidplatformdialoghelpers.h index 88ec91d936..7cbe21a9f4 100644 --- a/src/plugins/platforms/android/qandroidplatformdialoghelpers.h +++ b/src/plugins/platforms/android/qandroidplatformdialoghelpers.h @@ -46,6 +46,8 @@ #include <QEventLoop> #include <private/qjni_p.h> +QT_BEGIN_NAMESPACE + namespace QtAndroidDialogHelpers { class QAndroidPlatformMessageDialogHelper: public QPlatformMessageDialogHelper @@ -74,4 +76,6 @@ bool registerNatives(JNIEnv *env); } +QT_END_NAMESPACE + #endif // QANDROIDPLATFORMDIALOGHELPERS_H diff --git a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp index 935caed467..fd14f812a0 100644 --- a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp +++ b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp @@ -43,6 +43,8 @@ #include "qandroidplatformfontdatabase.h" +QT_BEGIN_NAMESPACE + QString QAndroidPlatformFontDatabase::fontDir() const { return QLatin1String("/system/fonts"); @@ -87,3 +89,5 @@ QStringList QAndroidPlatformFontDatabase::fallbacksForFamily(const QString &fami return QString(qgetenv("QT_ANDROID_FONTS")).split(";") + m_fallbacks[script]; } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformfontdatabase.h b/src/plugins/platforms/android/qandroidplatformfontdatabase.h index cdd3cf1674..0e961f8ae8 100644 --- a/src/plugins/platforms/android/qandroidplatformfontdatabase.h +++ b/src/plugins/platforms/android/qandroidplatformfontdatabase.h @@ -44,6 +44,8 @@ #include <QtPlatformSupport/private/qbasicfontdatabase_p.h> +QT_BEGIN_NAMESPACE + class QAndroidPlatformFontDatabase: public QBasicFontDatabase { public: @@ -58,4 +60,6 @@ private: QHash<QChar::Script, QStringList> m_fallbacks; }; +QT_END_NAMESPACE + #endif // QANDROIDPLATFORMFONTDATABASE_H diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index 213b1bb7e6..d6d7d3b173 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -74,6 +74,8 @@ QT_BEGIN_NAMESPACE int QAndroidPlatformIntegration::m_defaultGeometryWidth = 320; int QAndroidPlatformIntegration::m_defaultGeometryHeight = 455; +int QAndroidPlatformIntegration::m_defaultScreenWidth = 320; +int QAndroidPlatformIntegration::m_defaultScreenHeight = 455; int QAndroidPlatformIntegration::m_defaultPhysicalSizeWidth = 50; int QAndroidPlatformIntegration::m_defaultPhysicalSizeHeight = 71; @@ -121,7 +123,8 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList ¶ m_primaryScreen = new QAndroidPlatformScreen(); screenAdded(m_primaryScreen); m_primaryScreen->setPhysicalSize(QSize(m_defaultPhysicalSizeWidth, m_defaultPhysicalSizeHeight)); - m_primaryScreen->setGeometry(QRect(0, 0, m_defaultGeometryWidth, m_defaultGeometryHeight)); + m_primaryScreen->setAvailableGeometry(QRect(0, 0, m_defaultGeometryWidth, m_defaultGeometryHeight)); + m_primaryScreen->setSize(QSize(m_defaultScreenWidth, m_defaultScreenHeight)); m_mainThread = QThread::currentThread(); QtAndroid::setAndroidPlatformIntegration(this); @@ -312,12 +315,14 @@ QPlatformTheme *QAndroidPlatformIntegration::createPlatformTheme(const QString & return 0; } -void QAndroidPlatformIntegration::setDefaultDisplayMetrics(int gw, int gh, int sw, int sh) +void QAndroidPlatformIntegration::setDefaultDisplayMetrics(int gw, int gh, int sw, int sh, int screenWidth, int screenHeight) { m_defaultGeometryWidth = gw; m_defaultGeometryHeight = gh; m_defaultPhysicalSizeWidth = sw; m_defaultPhysicalSizeHeight = sh; + m_defaultScreenWidth = screenWidth; + m_defaultScreenHeight = screenHeight; } void QAndroidPlatformIntegration::setDefaultDesktopSize(int gw, int gh) @@ -345,7 +350,7 @@ QPlatformAccessibility *QAndroidPlatformIntegration::accessibility() const void QAndroidPlatformIntegration::setDesktopSize(int width, int height) { if (m_primaryScreen) - QMetaObject::invokeMethod(m_primaryScreen, "setGeometry", Qt::AutoConnection, Q_ARG(QRect, QRect(0,0,width, height))); + QMetaObject::invokeMethod(m_primaryScreen, "setAvailableGeometry", Qt::AutoConnection, Q_ARG(QRect, QRect(0,0,width, height))); } void QAndroidPlatformIntegration::setDisplayMetrics(int width, int height) @@ -354,4 +359,10 @@ void QAndroidPlatformIntegration::setDisplayMetrics(int width, int height) QMetaObject::invokeMethod(m_primaryScreen, "setPhysicalSize", Qt::AutoConnection, Q_ARG(QSize, QSize(width, height))); } +void QAndroidPlatformIntegration::setScreenSize(int width, int height) +{ + if (m_primaryScreen) + QMetaObject::invokeMethod(m_primaryScreen, "setSize", Qt::AutoConnection, Q_ARG(QSize, QSize(width, height))); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h index f8fa1a91dd..ce31516ace 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.h +++ b/src/plugins/platforms/android/qandroidplatformintegration.h @@ -86,6 +86,7 @@ public: virtual void setDesktopSize(int width, int height); virtual void setDisplayMetrics(int width, int height); + void setScreenSize(int width, int height); bool isVirtualDesktop() { return true; } QPlatformFontDatabase *fontDatabase() const; @@ -108,7 +109,7 @@ public: QStringList themeNames() const; QPlatformTheme *createPlatformTheme(const QString &name) const; - static void setDefaultDisplayMetrics(int gw, int gh, int sw, int sh); + static void setDefaultDisplayMetrics(int gw, int gh, int sw, int sh, int width, int height); static void setDefaultDesktopSize(int gw, int gh); static void setScreenOrientation(Qt::ScreenOrientation currentOrientation, Qt::ScreenOrientation nativeOrientation); @@ -135,6 +136,8 @@ private: static int m_defaultGeometryHeight; static int m_defaultPhysicalSizeWidth; static int m_defaultPhysicalSizeHeight; + static int m_defaultScreenWidth; + static int m_defaultScreenHeight; static Qt::ScreenOrientation m_orientation; static Qt::ScreenOrientation m_nativeOrientation; diff --git a/src/plugins/platforms/android/qandroidplatformmenu.cpp b/src/plugins/platforms/android/qandroidplatformmenu.cpp index 1ecabb25e2..b602f85cd9 100644 --- a/src/plugins/platforms/android/qandroidplatformmenu.cpp +++ b/src/plugins/platforms/android/qandroidplatformmenu.cpp @@ -43,6 +43,8 @@ #include "qandroidplatformmenuitem.h" #include "androidjnimenu.h" +QT_BEGIN_NAMESPACE + QAndroidPlatformMenu::QAndroidPlatformMenu() { m_tag = reinterpret_cast<quintptr>(this); // QMenu will overwrite this later, but we need a unique ID for QtQuick @@ -175,3 +177,5 @@ QMutex *QAndroidPlatformMenu::menuItemsMutex() { return &m_menuItemsMutex; } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformmenu.h b/src/plugins/platforms/android/qandroidplatformmenu.h index 305b64168a..7858ca36ae 100644 --- a/src/plugins/platforms/android/qandroidplatformmenu.h +++ b/src/plugins/platforms/android/qandroidplatformmenu.h @@ -46,6 +46,8 @@ #include <qvector.h> #include <qmutex.h> +QT_BEGIN_NAMESPACE + class QAndroidPlatformMenuItem; class QAndroidPlatformMenu: public QPlatformMenu { @@ -89,4 +91,6 @@ private: QMutex m_menuItemsMutex; }; +QT_END_NAMESPACE + #endif // QANDROIDPLATFORMMENU_H diff --git a/src/plugins/platforms/android/qandroidplatformmenubar.cpp b/src/plugins/platforms/android/qandroidplatformmenubar.cpp index 134062fb32..2d457296c5 100644 --- a/src/plugins/platforms/android/qandroidplatformmenubar.cpp +++ b/src/plugins/platforms/android/qandroidplatformmenubar.cpp @@ -43,6 +43,7 @@ #include "qandroidplatformmenu.h" #include "androidjnimenu.h" +QT_BEGIN_NAMESPACE QAndroidPlatformMenuBar::QAndroidPlatformMenuBar() { @@ -109,3 +110,5 @@ QMutex *QAndroidPlatformMenuBar::menusListMutex() { return &m_menusListMutex; } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformmenubar.h b/src/plugins/platforms/android/qandroidplatformmenubar.h index 56915335c2..52882b6922 100644 --- a/src/plugins/platforms/android/qandroidplatformmenubar.h +++ b/src/plugins/platforms/android/qandroidplatformmenubar.h @@ -46,6 +46,8 @@ #include <qvector.h> #include <qmutex.h> +QT_BEGIN_NAMESPACE + class QAndroidPlatformMenu; class QAndroidPlatformMenuBar: public QPlatformMenuBar { @@ -71,4 +73,6 @@ private: QMutex m_menusListMutex; }; +QT_END_NAMESPACE + #endif // QANDROIDPLATFORMMENUBAR_H diff --git a/src/plugins/platforms/android/qandroidplatformmenuitem.cpp b/src/plugins/platforms/android/qandroidplatformmenuitem.cpp index bd37834d2a..4e19ec2939 100644 --- a/src/plugins/platforms/android/qandroidplatformmenuitem.cpp +++ b/src/plugins/platforms/android/qandroidplatformmenuitem.cpp @@ -42,6 +42,8 @@ #include "qandroidplatformmenuitem.h" #include "qandroidplatformmenu.h" +QT_BEGIN_NAMESPACE + QAndroidPlatformMenuItem::QAndroidPlatformMenuItem() { m_tag = reinterpret_cast<quintptr>(this); // QMenu will overwrite this later, but we need a unique ID for QtQuick @@ -178,3 +180,5 @@ bool QAndroidPlatformMenuItem::isEnabled() const { return m_isEnabled; } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformmenuitem.h b/src/plugins/platforms/android/qandroidplatformmenuitem.h index 5861e8e195..40c3ab2761 100644 --- a/src/plugins/platforms/android/qandroidplatformmenuitem.h +++ b/src/plugins/platforms/android/qandroidplatformmenuitem.h @@ -43,6 +43,8 @@ #define QANDROIDPLATFORMMENUITEM_H #include <qpa/qplatformmenu.h> +QT_BEGIN_NAMESPACE + class QAndroidPlatformMenu; class QAndroidPlatformMenuItem: public QPlatformMenuItem @@ -96,4 +98,6 @@ private: bool m_isEnabled; }; +QT_END_NAMESPACE + #endif // QANDROIDPLATFORMMENUITEM_H diff --git a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp index 53047585cf..3a3ea71562 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp +++ b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp @@ -74,6 +74,7 @@ bool QAndroidPlatformOpenGLContext::needsFBOReadBackWorkaroud() needsWorkaround = qstrcmp(rendererString, "Mali-400 MP") == 0 || qstrcmp(rendererString, "Adreno (TM) 200") == 0 + || qstrcmp(rendererString, "Adreno (TM) 205") == 0 || qstrcmp(rendererString, "GC1000 core") == 0; set = true; } diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index e67a039ff4..af184cde02 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -86,7 +86,8 @@ private: QAndroidPlatformScreen::QAndroidPlatformScreen():QObject(),QPlatformScreen() { - m_geometry = QRect(0, 0, QAndroidPlatformIntegration::m_defaultGeometryWidth, QAndroidPlatformIntegration::m_defaultGeometryHeight); + m_availableGeometry = QRect(0, 0, QAndroidPlatformIntegration::m_defaultGeometryWidth, QAndroidPlatformIntegration::m_defaultGeometryHeight); + m_size = QSize(QAndroidPlatformIntegration::m_defaultScreenWidth, QAndroidPlatformIntegration::m_defaultScreenHeight); // Raster only apps should set QT_ANDROID_RASTER_IMAGE_DEPTH to 16 // is way much faster than 32 if (qgetenv("QT_ANDROID_RASTER_IMAGE_DEPTH").toInt() == 16) { @@ -204,7 +205,7 @@ void QAndroidPlatformScreen::scheduleUpdate() void QAndroidPlatformScreen::setDirty(const QRect &rect) { - QRect intersection = rect.intersected(m_geometry); + QRect intersection = rect.intersected(m_availableGeometry); m_dirtyRect |= intersection; scheduleUpdate(); } @@ -214,15 +215,21 @@ void QAndroidPlatformScreen::setPhysicalSize(const QSize &size) m_physicalSize = size; } -void QAndroidPlatformScreen::setGeometry(const QRect &rect) +void QAndroidPlatformScreen::setSize(const QSize &size) +{ + m_size = size; + QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry()); +} + +void QAndroidPlatformScreen::setAvailableGeometry(const QRect &rect) { QMutexLocker lock(&m_surfaceMutex); - if (m_geometry == rect) + if (m_availableGeometry == rect) return; - QRect oldGeometry = m_geometry; + QRect oldGeometry = m_availableGeometry; - m_geometry = rect; + m_availableGeometry = rect; QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry()); QWindowSystemInterface::handleScreenAvailableGeometryChange(QPlatformScreen::screen(), availableGeometry()); resizeMaximizedWindows(); @@ -231,9 +238,11 @@ void QAndroidPlatformScreen::setGeometry(const QRect &rect) QList<QWindow *> windows = QGuiApplication::allWindows(); for (int i = 0; i < windows.size(); ++i) { QWindow *w = windows.at(i); - QRect geometry = w->handle()->geometry(); - if (geometry.width() > 0 && geometry.height() > 0) - QWindowSystemInterface::handleExposeEvent(w, QRegion(geometry)); + if (w->handle()) { + QRect geometry = w->handle()->geometry(); + if (geometry.width() > 0 && geometry.height() > 0) + QWindowSystemInterface::handleExposeEvent(w, QRegion(geometry)); + } } } @@ -271,7 +280,7 @@ void QAndroidPlatformScreen::doRedraw() QMutexLocker lock(&m_surfaceMutex); if (m_id == -1 && m_rasterSurfaces) { - m_id = QtAndroid::createSurface(this, m_geometry, true, m_depth); + m_id = QtAndroid::createSurface(this, m_availableGeometry, true, m_depth); m_surfaceWaitCondition.wait(&m_surfaceMutex); } diff --git a/src/plugins/platforms/android/qandroidplatformscreen.h b/src/plugins/platforms/android/qandroidplatformscreen.h index 96a91fbf06..cd9cf2ca71 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.h +++ b/src/plugins/platforms/android/qandroidplatformscreen.h @@ -66,7 +66,8 @@ public: QAndroidPlatformScreen(); ~QAndroidPlatformScreen(); - QRect geometry() const { return m_geometry; } + QRect geometry() const { return QRect(QPoint(), m_size); } + QRect availableGeometry() const { return m_availableGeometry; } int depth() const { return m_depth; } QImage::Format format() const { return m_format; } QSizeF physicalSize() const { return m_physicalSize; } @@ -87,7 +88,8 @@ public: public slots: void setDirty(const QRect &rect); void setPhysicalSize(const QSize &size); - void setGeometry(const QRect &rect); + void setAvailableGeometry(const QRect &rect); + void setSize(const QSize &size); protected: typedef QList<QAndroidPlatformWindow *> WindowStackType; @@ -95,7 +97,7 @@ protected: QRect m_dirtyRect; QTimer m_redrawTimer; - QRect m_geometry; + QRect m_availableGeometry; int m_depth; QImage::Format m_format; QSizeF m_physicalSize; @@ -114,6 +116,7 @@ private: QAtomicInt m_rasterSurfaces = 0; ANativeWindow* m_nativeSurface = nullptr; QWaitCondition m_surfaceWaitCondition; + QSize m_size; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformservices.cpp b/src/plugins/platforms/android/qandroidplatformservices.cpp index 0df882f1f0..02fe29e576 100644 --- a/src/plugins/platforms/android/qandroidplatformservices.cpp +++ b/src/plugins/platforms/android/qandroidplatformservices.cpp @@ -44,6 +44,8 @@ #include <QDir> #include <QDebug> +QT_BEGIN_NAMESPACE + QAndroidPlatformServices::QAndroidPlatformServices() { QtAndroid::AttachedJNIEnv env; @@ -77,3 +79,5 @@ QByteArray QAndroidPlatformServices::desktopEnvironment() const { return QByteArray("Android"); } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformservices.h b/src/plugins/platforms/android/qandroidplatformservices.h index 8368b19043..08d7773ca4 100644 --- a/src/plugins/platforms/android/qandroidplatformservices.h +++ b/src/plugins/platforms/android/qandroidplatformservices.h @@ -46,6 +46,8 @@ #include "androidjnimain.h" #include <jni.h> +QT_BEGIN_NAMESPACE + class QAndroidPlatformServices: public QPlatformServices { public: @@ -58,4 +60,6 @@ private: }; +QT_END_NAMESPACE + #endif // ANDROIDPLATFORMDESKTOPSERVICE_H diff --git a/src/plugins/platforms/android/qandroidplatformtheme.cpp b/src/plugins/platforms/android/qandroidplatformtheme.cpp index 94e58eaeb6..1c9be189c8 100644 --- a/src/plugins/platforms/android/qandroidplatformtheme.cpp +++ b/src/plugins/platforms/android/qandroidplatformtheme.cpp @@ -50,6 +50,8 @@ #include <private/qguiapplication_p.h> #include <qandroidplatformintegration.h> +QT_BEGIN_NAMESPACE + QAndroidPlatformTheme::QAndroidPlatformTheme(QAndroidPlatformNativeInterface *androidPlatformNativeInterface) { m_androidPlatformNativeInterface = androidPlatformNativeInterface; @@ -240,3 +242,5 @@ QPlatformDialogHelper *QAndroidPlatformTheme::createPlatformDialogHelper(QPlatfo return 0; } } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformtheme.h b/src/plugins/platforms/android/qandroidplatformtheme.h index fecd7ca8e9..c37c9986c6 100644 --- a/src/plugins/platforms/android/qandroidplatformtheme.h +++ b/src/plugins/platforms/android/qandroidplatformtheme.h @@ -45,6 +45,8 @@ #include <qpa/qplatformtheme.h> #include <QtGui/qpalette.h> +QT_BEGIN_NAMESPACE + class QAndroidPlatformNativeInterface; class QAndroidPlatformTheme: public QPlatformTheme { @@ -66,4 +68,6 @@ private: QPalette m_defaultPalette; }; +QT_END_NAMESPACE + #endif // QANDROIDPLATFORMTHEME_H diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index a2f9f8c984..2f5355b180 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -223,7 +223,14 @@ static void cleanupCocoaApplicationDelegate() // events while the event loop is still running. const QWindowList topLevels = QGuiApplication::topLevelWindows(); for (int i = 0; i < topLevels.size(); ++i) { - QWindowSystemInterface::handleCloseEvent(topLevels.at(i)); + QWindow *topLevelWindow = topLevels.at(i); + // Widgets have alreay received a CloseEvent from the QApplication + // QCloseEvent handler. (see canQuit above). Prevent running the + // CloseEvent logic twice, call close() directly. + if (topLevelWindow->inherits("QWidgetWindow")) + topLevelWindow->close(); + else + QWindowSystemInterface::handleCloseEvent(topLevelWindow); } QWindowSystemInterface::flushWindowSystemEvents(); diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index e7f8992c6d..4328487f63 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -870,6 +870,9 @@ void QCocoaEventDispatcherPrivate::processPostedEvents() return; } + if (cleanupModalSessionsNeeded && currentExecIsNSAppRun) + cleanupModalSessions(); + if (processEventsCalled > 0 && interrupt) { if (currentExecIsNSAppRun) { // The event dispatcher has been interrupted. But since diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index d04dc958e1..4be49ed68f 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -158,23 +158,42 @@ qreal QCocoaScreen::devicePixelRatio() const QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const { - // Get a z-ordered list of windows. Iterate through it until - // we find a (Qt) window which contains the point. - for (NSWindow *nsWindow in [NSApp orderedWindows]) { - if (![nsWindow isKindOfClass:[QNSWindow class]]) + NSPoint screenPoint = qt_mac_flipPoint(point); + + // Search (hit test) for the top-level window. [NSWidow windowNumberAtPoint: + // belowWindowWithWindowNumber] may return windows that are not interesting + // to Qt. The search iterates until a suitable window or no window is found. + NSInteger topWindowNumber = 0; + QWindow *window = 0; + do { + // Get the top-most window, below any previously rejected window. + topWindowNumber = [NSWindow windowNumberAtPoint:screenPoint + belowWindowWithWindowNumber:topWindowNumber]; + + // Continue the search if the window does not belong to this process. + NSWindow *nsWindow = [NSApp windowWithWindowNumber:topWindowNumber]; + if (nsWindow == 0) continue; - QNSWindow *qnsWindow = static_cast<QNSWindow *>(nsWindow); - QCocoaWindow *cocoaWindow = qnsWindow.helper.platformWindow; + + // Continue the search if the window does not belong to Qt. + if (![nsWindow conformsToProtocol:@protocol(QNSWindowProtocol)]) + continue; + + id<QNSWindowProtocol> proto = static_cast<id<QNSWindowProtocol> >(nsWindow); + QCocoaWindow *cocoaWindow = proto.helper.platformWindow; if (!cocoaWindow) continue; - QWindow *window = cocoaWindow->window(); + window = cocoaWindow->window(); + + // Continue the search if the window is not a top-level window. if (!window->isTopLevel()) continue; - if (window->geometry().contains(point)) - return window; - } - return QPlatformScreen::topLevelAt(point); + // Stop searching. The current window is the correct window. + break; + } while (topWindowNumber > 0); + + return window; } extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev); diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index a0db46bf4b..53eee4a95d 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -54,6 +54,8 @@ class QCocoaBackingStore; class QCocoaGLContext; QT_END_NAMESPACE +Q_FORWARD_DECLARE_OBJC_CLASS(QNSViewMouseMoveHelper); + @interface QNSView : NSView <NSTextInputClient> { QCocoaBackingStore* m_backingStore; QPoint m_backingStoreOffset; @@ -74,6 +76,7 @@ QT_END_NAMESPACE bool m_shouldSetGLContextinDrawRect; #endif NSString *m_inputSource; + QNSViewMouseMoveHelper *m_mouseMoveHelper; } - (id)init; @@ -106,9 +109,10 @@ QT_END_NAMESPACE - (void)mouseDown:(NSEvent *)theEvent; - (void)mouseDragged:(NSEvent *)theEvent; - (void)mouseUp:(NSEvent *)theEvent; -- (void)mouseMoved:(NSEvent *)theEvent; -- (void)mouseEntered:(NSEvent *)theEvent; -- (void)mouseExited:(NSEvent *)theEvent; +- (void)mouseMovedImpl:(NSEvent *)theEvent; +- (void)mouseEnteredImpl:(NSEvent *)theEvent; +- (void)mouseExitedImpl:(NSEvent *)theEvent; +- (void)cursorUpdateImpl:(NSEvent *)theEvent; - (void)rightMouseDown:(NSEvent *)theEvent; - (void)rightMouseDragged:(NSEvent *)theEvent; - (void)rightMouseUp:(NSEvent *)theEvent; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index b023edf271..4a562f8a4e 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -77,6 +77,53 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; - (CGFloat)deviceDeltaZ; @end +@interface QNSViewMouseMoveHelper : NSObject +{ + QNSView *view; +} + +- (id)initWithView:(QNSView *)theView; + +- (void)mouseMoved:(NSEvent *)theEvent; +- (void)mouseEntered:(NSEvent *)theEvent; +- (void)mouseExited:(NSEvent *)theEvent; +- (void)cursorUpdate:(NSEvent *)theEvent; + +@end + +@implementation QNSViewMouseMoveHelper + +- (id)initWithView:(QNSView *)theView +{ + self = [super init]; + if (self) { + view = theView; + } + return self; +} + +- (void)mouseMoved:(NSEvent *)theEvent +{ + [view mouseMovedImpl:theEvent]; +} + +- (void)mouseEntered:(NSEvent *)theEvent +{ + [view mouseEnteredImpl:theEvent]; +} + +- (void)mouseExited:(NSEvent *)theEvent +{ + [view mouseExitedImpl:theEvent]; +} + +- (void)cursorUpdate:(NSEvent *)theEvent +{ + [view cursorUpdateImpl:theEvent]; +} + +@end + @implementation QNSView + (void)initialize @@ -104,6 +151,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; currentCustomDragTypes = 0; m_sendUpAsRightButton = false; m_inputSource = 0; + m_mouseMoveHelper = [[QNSViewMouseMoveHelper alloc] initWithView:self]; if (!touchDevice) { touchDevice = new QTouchDevice; @@ -123,6 +171,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; m_subscribesForGlobalFrameNotifications = false; [m_inputSource release]; [[NSNotificationCenter defaultCenter] removeObserver:self]; + [m_mouseMoveHelper release]; delete currentCustomDragTypes; @@ -761,13 +810,13 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; | NSTrackingInVisibleRect | NSTrackingMouseMoved | NSTrackingCursorUpdate; NSTrackingArea *ta = [[[NSTrackingArea alloc] initWithRect:[self frame] options:trackingOptions - owner:self + owner:m_mouseMoveHelper userInfo:nil] autorelease]; [self addTrackingArea:ta]; } --(void)cursorUpdate:(NSEvent *)theEvent +-(void)cursorUpdateImpl:(NSEvent *)theEvent { Q_UNUSED(theEvent) // Set the cursor manually if there is no NSWindow. @@ -784,10 +833,10 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; [self addCursorRect:[self visibleRect] cursor:m_platformWindow->m_windowCursor]; } -- (void)mouseMoved:(NSEvent *)theEvent +- (void)mouseMovedImpl:(NSEvent *)theEvent { if (m_window->flags() & Qt::WindowTransparentForInput) - return [super mouseMoved:theEvent]; + return; QPointF windowPoint; QPointF screenPoint; @@ -814,12 +863,13 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; [self handleMouseEvent: theEvent]; } -- (void)mouseEntered:(NSEvent *)theEvent +- (void)mouseEnteredImpl:(NSEvent *)theEvent { + Q_UNUSED(theEvent) m_platformWindow->m_windowUnderMouse = true; if (m_window->flags() & Qt::WindowTransparentForInput) - return [super mouseEntered:theEvent]; + return; // Top-level windows generate enter events for sub-windows. if (!m_platformWindow->m_nsWindow) @@ -832,13 +882,13 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; QWindowSystemInterface::handleEnterEvent(m_platformWindow->m_enterLeaveTargetWindow, windowPoint, screenPoint); } -- (void)mouseExited:(NSEvent *)theEvent +- (void)mouseExitedImpl:(NSEvent *)theEvent { + Q_UNUSED(theEvent); m_platformWindow->m_windowUnderMouse = false; if (m_window->flags() & Qt::WindowTransparentForInput) - return [super mouseExited:theEvent]; - Q_UNUSED(theEvent); + return; // Top-level windows generate leave events for sub-windows. if (!m_platformWindow->m_nsWindow) @@ -1324,7 +1374,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) QChar ch = QChar::ReplacementCharacter; int keyCode = Qt::Key_unknown; if ([characters length] != 0) { - if ((modifiers & Qt::MetaModifier) && ([charactersIgnoringModifiers length] != 0)) + if (((modifiers & Qt::MetaModifier) || (modifiers & Qt::AltModifier)) && ([charactersIgnoringModifiers length] != 0)) ch = QChar([charactersIgnoringModifiers characterAtIndex:0]); else ch = QChar([characters characterAtIndex:0]); diff --git a/src/plugins/platforms/directfb/main.cpp b/src/plugins/platforms/directfb/main.cpp index 423e33efd5..b0354c236d 100644 --- a/src/plugins/platforms/directfb/main.cpp +++ b/src/plugins/platforms/directfb/main.cpp @@ -75,7 +75,8 @@ QPlatformIntegration * QDirectFbIntegrationPlugin::create(const QString& system, if (!integration) return 0; - integration->initialize(); + integration->connectToDirectFb(); + return integration; } diff --git a/src/plugins/platforms/directfb/qdirectfbintegration.cpp b/src/plugins/platforms/directfb/qdirectfbintegration.cpp index 7ca7da8bcd..3d1b79ef38 100644 --- a/src/plugins/platforms/directfb/qdirectfbintegration.cpp +++ b/src/plugins/platforms/directfb/qdirectfbintegration.cpp @@ -64,7 +64,7 @@ QDirectFbIntegration::QDirectFbIntegration() { } -void QDirectFbIntegration::initialize() +void QDirectFbIntegration::connectToDirectFb() { initializeDirectFB(); initializeScreen(); diff --git a/src/plugins/platforms/directfb/qdirectfbintegration.h b/src/plugins/platforms/directfb/qdirectfbintegration.h index 5822202eea..b49600bed9 100644 --- a/src/plugins/platforms/directfb/qdirectfbintegration.h +++ b/src/plugins/platforms/directfb/qdirectfbintegration.h @@ -60,7 +60,7 @@ public: QDirectFbIntegration(); ~QDirectFbIntegration(); - void initialize(); + void connectToDirectFb(); QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const; QPlatformWindow *createPlatformWindow(QWindow *window) const; diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h index f3fd06037e..4403e3c28e 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.h +++ b/src/plugins/platforms/eglfs/qeglfswindow.h @@ -66,6 +66,8 @@ public: void lower() Q_DECL_OVERRIDE; void propagateSizeHints() Q_DECL_OVERRIDE { } + void setOpacity(qreal) Q_DECL_OVERRIDE { } + void setMask(const QRegion &) Q_DECL_OVERRIDE { } bool setKeyboardGrabEnabled(bool) Q_DECL_OVERRIDE { return false; } bool setMouseGrabEnabled(bool) Q_DECL_OVERRIDE { return false; } diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index 8be3846e06..d109d53168 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -54,7 +54,6 @@ QIOSInputContext *m_context; BOOL m_keyboardVisible; BOOL m_keyboardVisibleAndDocked; - BOOL m_ignoreKeyboardChanges; BOOL m_touchPressWhileKeyboardVisible; BOOL m_keyboardHiddenByGesture; QRectF m_keyboardRect; @@ -74,7 +73,6 @@ m_context = context; m_keyboardVisible = NO; m_keyboardVisibleAndDocked = NO; - m_ignoreKeyboardChanges = NO; m_touchPressWhileKeyboardVisible = NO; m_keyboardHiddenByGesture = NO; m_duration = 0; @@ -160,7 +158,7 @@ - (void) keyboardWillShow:(NSNotification *)notification { - if (m_ignoreKeyboardChanges) + if ([QUIView inUpdateKeyboardLayout]) return; // Note that UIKeyboardWillShowNotification is only sendt when the keyboard is docked. m_keyboardVisibleAndDocked = YES; @@ -175,7 +173,7 @@ - (void) keyboardWillHide:(NSNotification *)notification { - if (m_ignoreKeyboardChanges) + if ([QUIView inUpdateKeyboardLayout]) return; // Note that UIKeyboardWillHideNotification is also sendt when the keyboard is undocked. m_keyboardVisibleAndDocked = NO; @@ -407,11 +405,7 @@ void QIOSInputContext::update(Qt::InputMethodQueries query) void QIOSInputContext::reset() { - // Since the call to reset will cause a 'keyboardWillHide' - // notification to be sendt, we block keyboard nofifications to avoid artifacts: - m_keyboardListener->m_ignoreKeyboardChanges = true; [m_focusView reset]; - m_keyboardListener->m_ignoreKeyboardChanges = false; } void QIOSInputContext::commit() diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h index 91c4fc9dde..7c65037004 100644 --- a/src/plugins/platforms/ios/quiview.h +++ b/src/plugins/platforms/ios/quiview.h @@ -77,4 +77,5 @@ - (void)updateInputMethodWithQuery:(Qt::InputMethodQueries)query; - (void)reset; - (void)commit; ++ (bool)inUpdateKeyboardLayout; @end diff --git a/src/plugins/platforms/ios/quiview_textinput.mm b/src/plugins/platforms/ios/quiview_textinput.mm index 03006b3f99..e65ac1cc46 100644 --- a/src/plugins/platforms/ios/quiview_textinput.mm +++ b/src/plugins/platforms/ios/quiview_textinput.mm @@ -45,9 +45,12 @@ class StaticVariables { public: QInputMethodQueryEvent inputMethodQueryEvent; + bool inUpdateKeyboardLayout; QTextCharFormat markedTextFormat; - StaticVariables() : inputMethodQueryEvent(Qt::ImQueryInput) + StaticVariables() + : inputMethodQueryEvent(Qt::ImQueryInput) + , inUpdateKeyboardLayout(false) { // There seems to be no way to query how the preedit text // should be drawn. So we need to hard-code the color. @@ -152,6 +155,47 @@ Q_GLOBAL_STATIC(StaticVariables, staticVariables); return [super resignFirstResponder]; } ++ (bool)inUpdateKeyboardLayout +{ + return staticVariables()->inUpdateKeyboardLayout; +} + +- (void)updateKeyboardLayout +{ + if (![self isFirstResponder]) + return; + + // There seems to be no API to inform that the keyboard layout needs to update. + // As a work-around, we quickly resign first responder just to reassign it again. + QScopedValueRollback<bool> rollback(staticVariables()->inUpdateKeyboardLayout); + staticVariables()->inUpdateKeyboardLayout = true; + [super resignFirstResponder]; + [self updateTextInputTraits]; + [super becomeFirstResponder]; +} + +- (void)updateUITextInputDelegate:(NSNumber *)intQuery +{ + // As documented, we should not report textWillChange/textDidChange unless the text + // was changed externally. That will cause spell checking etc to fail. But we don't + // really know if the text/selection was changed by UITextInput or Qt/app when getting + // update calls from Qt. We therefore use a less ideal approach where we always assume + // that UITextView caused the change if we're currently processing an event sendt from it. + if (m_inSendEventToFocusObject) + return; + + Qt::InputMethodQueries query = Qt::InputMethodQueries([intQuery intValue]); + if (query & (Qt::ImCursorPosition | Qt::ImAnchorPosition)) { + [self.inputDelegate selectionWillChange:id<UITextInput>(self)]; + [self.inputDelegate selectionDidChange:id<UITextInput>(self)]; + } + + if (query & Qt::ImSurroundingText) { + [self.inputDelegate textWillChange:id<UITextInput>(self)]; + [self.inputDelegate textDidChange:id<UITextInput>(self)]; + } +} + - (void)updateInputMethodWithQuery:(Qt::InputMethodQueries)query { Q_UNUSED(query); @@ -160,26 +204,13 @@ Q_GLOBAL_STATIC(StaticVariables, staticVariables); if (!focusObject) return; - if (!m_inSendEventToFocusObject) { - if (query & (Qt::ImCursorPosition | Qt::ImAnchorPosition)) - [self.inputDelegate selectionWillChange:id<UITextInput>(self)]; - if (query & Qt::ImSurroundingText) - [self.inputDelegate textWillChange:id<UITextInput>(self)]; - } - // Note that we ignore \a query, and instead update using Qt::ImQueryInput. This enables us to just // store the event without copying out the result from the event each time. Besides, we seem to be // called with Qt::ImQueryInput when only changing selection, and always if typing text. So there would // not be any performance gain by only updating \a query. staticVariables()->inputMethodQueryEvent = QInputMethodQueryEvent(Qt::ImQueryInput); QCoreApplication::sendEvent(focusObject, &staticVariables()->inputMethodQueryEvent); - - if (!m_inSendEventToFocusObject) { - if (query & (Qt::ImCursorPosition | Qt::ImAnchorPosition)) - [self.inputDelegate selectionDidChange:id<UITextInput>(self)]; - if (query & Qt::ImSurroundingText) - [self.inputDelegate textDidChange:id<UITextInput>(self)]; - } + [self updateUITextInputDelegate:[NSNumber numberWithInt:int(query)]]; } - (void)sendEventToFocusObject:(QEvent &)e @@ -189,35 +220,31 @@ Q_GLOBAL_STATIC(StaticVariables, staticVariables); return; // While sending the event, we will receive back updateInputMethodWithQuery calls. - // To not confuse iOS, we cannot not call textWillChange/textDidChange at that - // point since it will cause spell checking etc to fail. So we use a guard. + // Note that it would be more correct to post the event instead, but UITextInput expects + // callbacks to take effect immediately (it will query us for information after a callback). + QScopedValueRollback<BOOL> rollback(m_inSendEventToFocusObject); m_inSendEventToFocusObject = YES; QCoreApplication::sendEvent(focusObject, &e); - m_inSendEventToFocusObject = NO; } - (void)reset { - [self.inputDelegate textWillChange:id<UITextInput>(self)]; [self setMarkedText:@"" selectedRange:NSMakeRange(0, 0)]; [self updateInputMethodWithQuery:Qt::ImQueryInput]; - - if ([self isFirstResponder]) { - // There seem to be no way to inform that the keyboard needs to update (since - // text input traits might have changed). As a work-around, we quickly resign - // first responder status just to reassign it again: - [super resignFirstResponder]; - [self updateTextInputTraits]; - [super becomeFirstResponder]; - } - [self.inputDelegate textDidChange:id<UITextInput>(self)]; + // Guard agains recursive callbacks by posting calls to UITextInput + [self performSelectorOnMainThread:@selector(updateKeyboardLayout) withObject:nil waitUntilDone:NO]; + [self performSelectorOnMainThread:@selector(updateUITextInputDelegate:) + withObject:[NSNumber numberWithInt:int(Qt::ImQueryInput)] + waitUntilDone:NO]; } - (void)commit { - [self.inputDelegate textWillChange:id<UITextInput>(self)]; [self unmarkText]; - [self.inputDelegate textDidChange:id<UITextInput>(self)]; + // Guard agains recursive callbacks by posting calls to UITextInput + [self performSelectorOnMainThread:@selector(updateUITextInputDelegate:) + withObject:[NSNumber numberWithInt:int(Qt::ImSurroundingText)] + waitUntilDone:NO]; } - (QVariant)imValue:(Qt::InputMethodQuery)query diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index 53b48ee37f..9a17f807a9 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -522,6 +522,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locale(IA2Locale *locale) QLocale l; res.country = QStringToBSTR(QLocale::countryToString(l.country())); res.language = QStringToBSTR(QLocale::languageToString(l.language())); + res.variant = QStringToBSTR(QString()); *locale = res; return S_OK; } diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h index 9c922dce36..9c42fdc631 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.h +++ b/src/plugins/platforms/windows/accessible/iaccessible2.h @@ -329,7 +329,7 @@ public: private: static BSTR relationToBSTR(QAccessible::Relation relation) { - wchar_t *constRelationString = 0; + const wchar_t *constRelationString = 0; switch (relation) { case QAccessible::Label: constRelationString = IA2_RELATION_LABEL_FOR; diff --git a/src/plugins/platforms/windows/qplatformfunctions_wince.h b/src/plugins/platforms/windows/qplatformfunctions_wince.h index 65ce466086..921e64d64c 100644 --- a/src/plugins/platforms/windows/qplatformfunctions_wince.h +++ b/src/plugins/platforms/windows/qplatformfunctions_wince.h @@ -271,14 +271,19 @@ typedef struct tagTTPOLYCURVE #define WM_DRAWCLIPBOARD 0x0308 #endif +#include <QFileInfo> + inline bool IsIconic( HWND /*hWnd*/ ) { return false; } -inline int AddFontResourceExW( LPCWSTR /*name*/, DWORD /*fl*/, PVOID /*res*/) +inline int AddFontResourceExW( LPCWSTR name, DWORD /*fl*/, PVOID /*res*/) { - return 0; + QString fName = QString::fromWCharArray(name); + QFileInfo fileinfo(fName); + fName = fileinfo.absoluteFilePath(); + return AddFontResource((LPCWSTR)fName.utf16()); } inline bool RemoveFontResourceExW( LPCWSTR /*name*/, DWORD /*fl*/, PVOID /*pdv*/) diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index 0b257cc48f..6bcfe01a18 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -893,6 +893,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms case Qt::Key_Plus: case Qt::Key_Minus: case Qt::Key_Period: + case Qt::Key_Comma: case Qt::Key_0: case Qt::Key_1: case Qt::Key_2: diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index cc0597b72d..4633378342 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -178,10 +178,11 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, // since we do not want to ignore mouse events coming from a tablet. const quint64 extraInfo = GetMessageExtraInfo(); if ((extraInfo & signatureMask) == miWpSignature) { - source = Qt::MouseEventSynthesizedBySystem; - const bool fromTouch = extraInfo & 0x80; // (else: Tablet PC) - if (fromTouch && !passSynthesizedMouseEvents) - return false; + if (extraInfo & 0x80) { // Bit 7 indicates touch event, else tablet pen. + source = Qt::MouseEventSynthesizedBySystem; + if (!passSynthesizedMouseEvents) + return false; + } } #endif // !Q_OS_WINCE diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 1b91ba8e1b..18b4cc85cc 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1969,7 +1969,10 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const && (m_data.flags & Qt::FramelessWindowHint)) { // This block fixes QTBUG-8361: Frameless windows shouldn't cover the // taskbar when maximized - if (const QScreen *screen = window()->screen()) { + const QScreen *screen = window()->screen(); + + // Documentation of MINMAXINFO states that it will only work for the primary screen + if (screen && screen == QGuiApplication::primaryScreen()) { mmi->ptMaxSize.y = screen->availableGeometry().height(); // Width, because you can have the taskbar on the sides too. @@ -1978,8 +1981,8 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const // If you have the taskbar on top, or on the left you don't want it at (0,0): mmi->ptMaxPosition.x = screen->availableGeometry().x(); mmi->ptMaxPosition.y = screen->availableGeometry().y(); - } else { - qWarning() << "Invalid screen"; + } else if (!screen){ + qWarning() << "effectiveScreen() returned a null screen"; } } diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 1b72bb0da1..7f23c84cb9 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1028,6 +1028,15 @@ void QXcbEventReader::registerForEvents() connect(dispatcher, SIGNAL(awake()), m_connection, SLOT(processXcbEvents())); } +void QXcbEventReader::registerEventDispatcher(QAbstractEventDispatcher *dispatcher) +{ + // flush the xcb connection before the EventDispatcher is going to block + // In the non-threaded case processXcbEvents is called before going to block, + // which flushes the connection. + if (m_xcb_poll_for_queued_event) + connect(dispatcher, SIGNAL(aboutToBlock()), m_connection, SLOT(flush())); +} + void QXcbEventReader::run() { xcb_generic_event_t *event; diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 12143a7e4b..15fdf50a1e 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -311,6 +311,8 @@ public: void start(); + void registerEventDispatcher(QAbstractEventDispatcher *dispatcher); + signals: void eventPending(); @@ -410,7 +412,6 @@ public: void sync(); - void flush() { xcb_flush(m_connection); } void handleXcbError(xcb_generic_error_t *error); void handleXcbEvent(xcb_generic_event_t *event); @@ -465,8 +466,11 @@ public: void handleEnterEvent(const xcb_enter_notify_event_t *); #endif + QXcbEventReader *eventReader() const { return m_reader; } + public slots: void syncWindow(QXcbWindow *window); + void flush() { xcb_flush(m_connection); } private slots: void processXcbEvents(); @@ -497,8 +501,10 @@ private: #ifdef XCB_USE_XINPUT2 void initializeXInput2(); void finalizeXInput2(); + void xi2SetupDevices(); XInput2DeviceData *deviceForId(int id); void xi2HandleEvent(xcb_ge_event_t *event); + void xi2HandleHierachyEvent(void *event); int m_xiOpCode, m_xiEventBase, m_xiErrorBase; #ifndef QT_NO_TABLETEVENT struct TabletData { diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index eb7b220c43..a574dcae6c 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -73,10 +73,6 @@ void QXcbConnection::initializeXInput2() { debug_xinput = qEnvironmentVariableIsSet("QT_XCB_DEBUG_XINPUT"); debug_xinput_devices = qEnvironmentVariableIsSet("QT_XCB_DEBUG_XINPUT_DEVICES"); -#ifndef QT_NO_TABLETEVENT - m_tabletData.clear(); -#endif - m_scrollingDevices.clear(); Display *xDisplay = static_cast<Display *>(m_xlib_display); if (XQueryExtension(xDisplay, "XInputExtension", &m_xiOpCode, &m_xiEventBase, &m_xiErrorBase)) { int xiMajor = 2; @@ -97,126 +93,146 @@ void QXcbConnection::initializeXInput2() #else qDebug("XInput version %d.%d is available and Qt supports 2.0", xiMajor, m_xi2Minor); #endif - int deviceCount = 0; - XIDeviceInfo *devices = XIQueryDevice(xDisplay, XIAllDevices, &deviceCount); - for (int i = 0; i < deviceCount; ++i) { - // Only non-master pointing devices are relevant here. - if (devices[i].use != XISlavePointer) - continue; - if (Q_UNLIKELY(debug_xinput_devices)) - qDebug() << "input device "<< devices[i].name; + } + + xi2SetupDevices(); + } +} + +void QXcbConnection::xi2SetupDevices() +{ +#ifndef QT_NO_TABLETEVENT + m_tabletData.clear(); +#endif + m_scrollingDevices.clear(); + + if (!m_xi2Enabled) + return; + + Display *xDisplay = static_cast<Display *>(m_xlib_display); + int deviceCount = 0; + XIDeviceInfo *devices = XIQueryDevice(xDisplay, XIAllDevices, &deviceCount); + for (int i = 0; i < deviceCount; ++i) { + // Only non-master pointing devices are relevant here. + if (devices[i].use != XISlavePointer) + continue; + if (Q_UNLIKELY(debug_xinput_devices)) + qDebug() << "input device "<< devices[i].name; #ifndef QT_NO_TABLETEVENT - TabletData tabletData; + TabletData tabletData; #endif - ScrollingDevice scrollingDevice; - for (int c = 0; c < devices[i].num_classes; ++c) { - switch (devices[i].classes[c]->type) { - case XIValuatorClass: { - XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(devices[i].classes[c]); - const int valuatorAtom = qatom(vci->label); - if (Q_UNLIKELY(debug_xinput_devices)) - qDebug() << " has valuator" << atomName(vci->label) << "recognized?" << (valuatorAtom < QXcbAtom::NAtoms); + ScrollingDevice scrollingDevice; + for (int c = 0; c < devices[i].num_classes; ++c) { + switch (devices[i].classes[c]->type) { + case XIValuatorClass: { + XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(devices[i].classes[c]); + const int valuatorAtom = qatom(vci->label); + if (Q_UNLIKELY(debug_xinput_devices)) + qDebug() << " has valuator" << atomName(vci->label) << "recognized?" << (valuatorAtom < QXcbAtom::NAtoms); #ifndef QT_NO_TABLETEVENT - if (valuatorAtom < QXcbAtom::NAtoms) { - TabletData::ValuatorClassInfo info; - info.minVal = vci->min; - info.maxVal = vci->max; - info.number = vci->number; - tabletData.valuatorInfo[valuatorAtom] = info; - } + if (valuatorAtom < QXcbAtom::NAtoms) { + TabletData::ValuatorClassInfo info; + info.minVal = vci->min; + info.maxVal = vci->max; + info.number = vci->number; + tabletData.valuatorInfo[valuatorAtom] = info; + } #endif // QT_NO_TABLETEVENT - if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel) - scrollingDevice.lastScrollPosition.setX(vci->value); - else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel) - scrollingDevice.lastScrollPosition.setY(vci->value); - break; - } + if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel) + scrollingDevice.lastScrollPosition.setX(vci->value); + else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel) + scrollingDevice.lastScrollPosition.setY(vci->value); + break; + } #ifdef XCB_USE_XINPUT21 - case XIScrollClass: { - XIScrollClassInfo *sci = reinterpret_cast<XIScrollClassInfo *>(devices[i].classes[c]); - if (sci->scroll_type == XIScrollTypeVertical) { - scrollingDevice.orientations |= Qt::Vertical; - scrollingDevice.verticalIndex = sci->number; - scrollingDevice.verticalIncrement = sci->increment; - } - else if (sci->scroll_type == XIScrollTypeHorizontal) { - scrollingDevice.orientations |= Qt::Horizontal; - scrollingDevice.horizontalIndex = sci->number; - scrollingDevice.horizontalIncrement = sci->increment; - } - break; - } - case XIButtonClass: { - XIButtonClassInfo *bci = reinterpret_cast<XIButtonClassInfo *>(devices[i].classes[c]); - if (bci->num_buttons >= 5) { - Atom label4 = bci->labels[3]; - Atom label5 = bci->labels[4]; - if ((!label4 || qatom(label4) == QXcbAtom::ButtonWheelUp) && (!label5 || qatom(label5) == QXcbAtom::ButtonWheelDown)) - scrollingDevice.legacyOrientations |= Qt::Vertical; - } - if (bci->num_buttons >= 7) { - Atom label6 = bci->labels[5]; - Atom label7 = bci->labels[6]; - if ((!label6 || qatom(label6) == QXcbAtom::ButtonHorizWheelLeft) && (!label7 || qatom(label7) == QXcbAtom::ButtonHorizWheelRight)) - scrollingDevice.legacyOrientations |= Qt::Horizontal; - } - break; - } -#endif - default: - break; - } + case XIScrollClass: { + XIScrollClassInfo *sci = reinterpret_cast<XIScrollClassInfo *>(devices[i].classes[c]); + if (sci->scroll_type == XIScrollTypeVertical) { + scrollingDevice.orientations |= Qt::Vertical; + scrollingDevice.verticalIndex = sci->number; + scrollingDevice.verticalIncrement = sci->increment; } - bool isTablet = false; -#ifndef QT_NO_TABLETEVENT - // If we have found the valuators which we expect a tablet to have, assume it's a tablet. - if (tabletData.valuatorInfo.contains(QXcbAtom::AbsX) && - tabletData.valuatorInfo.contains(QXcbAtom::AbsY) && - tabletData.valuatorInfo.contains(QXcbAtom::AbsPressure)) { - tabletData.deviceId = devices[i].deviceid; - tabletData.pointerType = QTabletEvent::Pen; - if (QByteArray(devices[i].name).toLower().contains("eraser")) - tabletData.pointerType = QTabletEvent::Eraser; - m_tabletData.append(tabletData); - isTablet = true; - if (Q_UNLIKELY(debug_xinput_devices)) - qDebug() << " it's a tablet with pointer type" << tabletData.pointerType; + else if (sci->scroll_type == XIScrollTypeHorizontal) { + scrollingDevice.orientations |= Qt::Horizontal; + scrollingDevice.horizontalIndex = sci->number; + scrollingDevice.horizontalIncrement = sci->increment; + } + break; + } + case XIButtonClass: { + XIButtonClassInfo *bci = reinterpret_cast<XIButtonClassInfo *>(devices[i].classes[c]); + if (bci->num_buttons >= 5) { + Atom label4 = bci->labels[3]; + Atom label5 = bci->labels[4]; + if ((!label4 || qatom(label4) == QXcbAtom::ButtonWheelUp) && (!label5 || qatom(label5) == QXcbAtom::ButtonWheelDown)) + scrollingDevice.legacyOrientations |= Qt::Vertical; } + if (bci->num_buttons >= 7) { + Atom label6 = bci->labels[5]; + Atom label7 = bci->labels[6]; + if ((!label6 || qatom(label6) == QXcbAtom::ButtonHorizWheelLeft) && (!label7 || qatom(label7) == QXcbAtom::ButtonHorizWheelRight)) + scrollingDevice.legacyOrientations |= Qt::Horizontal; + } + break; + } +#endif + default: + break; + } + } + bool isTablet = false; +#ifndef QT_NO_TABLETEVENT + // If we have found the valuators which we expect a tablet to have, assume it's a tablet. + if (tabletData.valuatorInfo.contains(QXcbAtom::AbsX) && + tabletData.valuatorInfo.contains(QXcbAtom::AbsY) && + tabletData.valuatorInfo.contains(QXcbAtom::AbsPressure)) { + tabletData.deviceId = devices[i].deviceid; + tabletData.pointerType = QTabletEvent::Pen; + if (QByteArray(devices[i].name).toLower().contains("eraser")) + tabletData.pointerType = QTabletEvent::Eraser; + m_tabletData.append(tabletData); + isTablet = true; + if (Q_UNLIKELY(debug_xinput_devices)) + qDebug() << " it's a tablet with pointer type" << tabletData.pointerType; + } #endif // QT_NO_TABLETEVENT #ifdef XCB_USE_XINPUT21 - if (scrollingDevice.orientations || scrollingDevice.legacyOrientations) { - scrollingDevice.deviceId = devices[i].deviceid; - // Only use legacy wheel button events when we don't have real scroll valuators. - scrollingDevice.legacyOrientations &= ~scrollingDevice.orientations; - m_scrollingDevices.insert(scrollingDevice.deviceId, scrollingDevice); - if (Q_UNLIKELY(debug_xinput_devices)) - qDebug() << " it's a scrolling device"; - } + if (scrollingDevice.orientations || scrollingDevice.legacyOrientations) { + scrollingDevice.deviceId = devices[i].deviceid; + // Only use legacy wheel button events when we don't have real scroll valuators. + scrollingDevice.legacyOrientations &= ~scrollingDevice.orientations; + m_scrollingDevices.insert(scrollingDevice.deviceId, scrollingDevice); + if (Q_UNLIKELY(debug_xinput_devices)) + qDebug() << " it's a scrolling device"; + } #endif - if (!isTablet) { - XInput2DeviceData *dev = deviceForId(devices[i].deviceid); - if (Q_UNLIKELY(debug_xinput_devices)) { - if (dev && dev->qtTouchDevice->type() == QTouchDevice::TouchScreen) - qDebug(" it's a touchscreen with type %d capabilities 0x%X max touch points %d", - dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), - dev->qtTouchDevice->maximumTouchPoints()); - else if (dev && dev->qtTouchDevice->type() == QTouchDevice::TouchPad) - qDebug(" it's a touchpad with type %d capabilities 0x%X max touch points %d size %f x %f", - dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), - dev->qtTouchDevice->maximumTouchPoints(), - dev->size.width(), dev->size.height()); - } - } + if (!isTablet) { + XInput2DeviceData *dev = deviceForId(devices[i].deviceid); + if (Q_UNLIKELY(debug_xinput_devices)) { + if (dev && dev->qtTouchDevice->type() == QTouchDevice::TouchScreen) + qDebug(" it's a touchscreen with type %d capabilities 0x%X max touch points %d", + dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), + dev->qtTouchDevice->maximumTouchPoints()); + else if (dev && dev->qtTouchDevice->type() == QTouchDevice::TouchPad) + qDebug(" it's a touchpad with type %d capabilities 0x%X max touch points %d size %f x %f", + dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), + dev->qtTouchDevice->maximumTouchPoints(), + dev->size.width(), dev->size.height()); } - XIFreeDeviceInfo(devices); } } + XIFreeDeviceInfo(devices); } void QXcbConnection::finalizeXInput2() { + foreach (XInput2DeviceData *dev, m_touchDevices) { + if (dev->xiDeviceInfo) + XIFreeDeviceInfo(dev->xiDeviceInfo); + delete dev; + } } void QXcbConnection::xi2Select(xcb_window_t window) @@ -303,6 +319,16 @@ void QXcbConnection::xi2Select(xcb_window_t window) #else Q_UNUSED(xiBitMask); #endif + + { + // Listen for hotplug events + XIEventMask xiEventMask; + bitMask = XI_HierarchyChangedMask; + xiEventMask.deviceid = XIAllDevices; + xiEventMask.mask_len = sizeof(bitMask); + xiEventMask.mask = xiBitMask; + XISelectEvents(xDisplay, window, &xiEventMask, 1); + } } XInput2DeviceData *QXcbConnection::deviceForId(int id) @@ -326,10 +352,10 @@ XInput2DeviceData *QXcbConnection::deviceForId(int id) if (Q_UNLIKELY(debug_xinput_devices)) qDebug(" has touch class with mode %d", tci->mode); switch (tci->mode) { - case XIModeRelative: + case XIDependentTouch: type = QTouchDevice::TouchPad; break; - case XIModeAbsolute: + case XIDirectTouch: type = QTouchDevice::TouchScreen; break; } @@ -372,6 +398,7 @@ XInput2DeviceData *QXcbConnection::deviceForId(int id) m_touchDevices[id] = dev; } else { m_touchDevices.remove(id); + XIFreeDeviceInfo(dev->xiDeviceInfo); delete dev; dev = 0; } @@ -402,6 +429,10 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) if (xi2PrepareXIGenericDeviceEvent(event, m_xiOpCode)) { xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event); + if (xiEvent->evtype == XI_HierarchyChanged) { + xi2HandleHierachyEvent(xiEvent); + return; + } #ifndef QT_NO_TABLETEVENT for (int i = 0; i < m_tabletData.count(); ++i) { if (m_tabletData.at(i).deviceId == xiEvent->deviceid) { @@ -561,6 +592,19 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) } } +void QXcbConnection::xi2HandleHierachyEvent(void *event) +{ + xXIHierarchyEvent *xiEvent = reinterpret_cast<xXIHierarchyEvent *>(event); + // We only care about hotplugged devices + if (!(xiEvent->flags & (XISlaveRemoved | XISlaveAdded))) + return; + xi2SetupDevices(); + // Reselect events for all event-listening windows. + Q_FOREACH (xcb_window_t window, m_mapper.keys()) { + xi2Select(window); + } +} + void QXcbConnection::handleEnterEvent(const xcb_enter_notify_event_t *) { #ifdef XCB_USE_XINPUT21 diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 36a4b5c5db..f537a38962 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -316,7 +316,10 @@ bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const QAbstractEventDispatcher *QXcbIntegration::createEventDispatcher() const { - return createUnixEventDispatcher(); + QAbstractEventDispatcher *dispatcher = createUnixEventDispatcher(); + for (int i = 0; i < m_connections.size(); i++) + m_connections[i]->eventReader()->registerEventDispatcher(dispatcher); + return dispatcher; } void QXcbIntegration::initialize() diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 69601f44d4..4c84b19f82 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -929,6 +929,15 @@ int QXcbKeyboard::keysymToQtKey(xcb_keysym_t key) const i += 2; } + if (rmod_masks.meta) { + // translate Super/Hyper keys to Meta if we're using them as the MetaModifier + if (rmod_masks.meta == rmod_masks.super && (code == Qt::Key_Super_L || code == Qt::Key_Super_R)) { + code = Qt::Key_Meta; + } else if (rmod_masks.meta == rmod_masks.hyper && (code == Qt::Key_Hyper_L || code == Qt::Key_Hyper_R)) { + code = Qt::Key_Meta; + } + } + return code; } diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 9f19841437..01e78465b6 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -106,6 +106,11 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr, qDebug(" root ID........: %x", screen()->root); #endif + QScopedPointer<xcb_get_window_attributes_reply_t, QScopedPointerPodDeleter> rootAttribs( + xcb_get_window_attributes_reply(xcb_connection(), + xcb_get_window_attributes_unchecked(xcb_connection(), screen()->root), NULL)); + const quint32 existingEventMask = rootAttribs.isNull() ? 0 : rootAttribs->your_event_mask; + const quint32 mask = XCB_CW_EVENT_MASK; const quint32 values[] = { // XCB_CW_EVENT_MASK @@ -113,6 +118,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr, | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY // for the "MANAGER" atom (system tray notification). + | existingEventMask // don't overwrite the event mask on the root window }; xcb_change_window_attributes(xcb_connection(), screen()->root, mask, values); diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 4b9a99486f..dd3084e402 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -339,12 +339,38 @@ void QXcbWindow::create() #endif //defined(XCB_USE_GLX) || defined(XCB_USE_EGL) { m_window = xcb_generate_id(xcb_connection()); + m_visualId = m_screen->screen()->root_visual; m_depth = m_screen->screen()->root_depth; + + uint32_t mask = 0; + uint32_t values[3]; + + if (m_format.alphaBufferSize() == 8) { + xcb_depth_iterator_t depthIter = xcb_screen_allowed_depths_iterator(m_screen->screen()); + while (depthIter.rem) { + if (depthIter.data->depth == 32) { + xcb_visualtype_iterator_t visualIter = xcb_depth_visuals_iterator(depthIter.data); + if (visualIter.rem) { + m_visualId = visualIter.data->visual_id; + m_depth = 32; + uint32_t colormap = xcb_generate_id(xcb_connection()); + xcb_create_colormap(xcb_connection(), XCB_COLORMAP_ALLOC_NONE, colormap, + xcb_parent_id, m_visualId); + mask |= XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP; + values[0] = m_screen->screen()->white_pixel; + values[1] = m_screen->screen()->black_pixel; + values[2] = colormap; + break; + } + } + xcb_depth_next(&depthIter); + } + } + m_imageFormat = imageFormatForDepth(m_depth); - m_visualId = m_screen->screen()->root_visual; Q_XCB_CALL(xcb_create_window(xcb_connection(), - XCB_COPY_FROM_PARENT, // depth -- same as root + m_depth, m_window, // window id xcb_parent_id, // parent window id rect.x(), @@ -354,8 +380,8 @@ void QXcbWindow::create() 0, // border width XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class m_visualId, // visual - 0, // value mask - 0)); // value list + mask, + values)); } connection()->addWindowEventListener(m_window, this); diff --git a/src/plugins/platforms/xcb/xcb-plugin.pro b/src/plugins/platforms/xcb/xcb-plugin.pro index a52aaa4a2e..4d76e4d449 100644 --- a/src/plugins/platforms/xcb/xcb-plugin.pro +++ b/src/plugins/platforms/xcb/xcb-plugin.pro @@ -109,7 +109,6 @@ QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XCB CONFIG += qpa/genericunixfontdatabase contains(QT_CONFIG, dbus) { -DEFINES += XCB_USE_IBUS QT += dbus LIBS += -ldbus-1 } diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp index 2c75ab7016..915d8380c7 100644 --- a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp +++ b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp @@ -252,6 +252,9 @@ QMarginsF QWindowsPrintDevice::printableMargins(const QPageSize &pageSize, if (GetPrinter(m_hPrinter, 2, buffer.data(), needed, &needed)) { PPRINTER_INFO_2 info = reinterpret_cast<PPRINTER_INFO_2>(buffer.data()); DEVMODE *devMode = info->pDevMode; + if (!devMode) + return margins; + HDC pDC = CreateDC(NULL, (LPWSTR)m_id.utf16(), NULL, devMode); if (pageSize.id() == QPageSize::Custom || pageSize.windowsId() <= 0 || pageSize.windowsId() > DMPAPER_LAST) { devMode->dmPaperSize = 0; |