From 1dd9a0af4f577ccb5578cea562a98686c8e290e6 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 9 Jul 2014 09:49:59 +0200 Subject: [PATCH 01/11] Fix fallbacks for adapted common script When the platform plugin gives us specific fallbacks for a specific script, we need to respect this, and load the correct font family regardless of which writing systems it supports. This is especially important since the common script is adapted to match surrounding, proper scripts, so characters such as digits next to e.g. Hebrew text will be marked as Hebrew. On stock Android, there is a single Hebrew font, and this would previously be put in all fallback slots for Hebrew regardless of what fallback fonts were dictated by the platform plugin. Since this font does not support the digits, they would show up as boxes. [ChangeLog][Android] Fixed common characters like digits and punctuation showing as boxes when positioned next to non-latin scripts. Task-number: QTBUG-39377 Change-Id: I1555e208a8ddc587c0bbdbfff1600cafdd9442e9 Reviewed-by: Konstantin Ritt --- src/gui/text/qfontdatabase.cpp | 10 ++++---- src/gui/text/qfontdatabase.h | 2 +- src/gui/text/qfontengine_qpa.cpp | 2 +- .../gui/text/qfontdatabase/qfontdatabase.pro | 5 ++++ .../auto/gui/text/qfontdatabase/testdata.qrc | 5 ++++ .../text/qfontdatabase/tst_qfontdatabase.cpp | 24 +++++++++++++++++++ 6 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 tests/auto/gui/text/qfontdatabase/testdata.qrc diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 06438103ad..86a0bf1066 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -596,7 +596,7 @@ struct QtFontDesc static int match(int script, const QFontDef &request, const QString &family_name, const QString &foundry_name, int force_encoding_id, - QtFontDesc *desc, const QList &blacklisted); + QtFontDesc *desc, const QList &blacklisted, bool fallback); static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDef *fontDef, bool multi) { @@ -1079,7 +1079,7 @@ static bool matchFamilyName(const QString &familyName, QtFontFamily *f) */ static int match(int script, const QFontDef &request, const QString &family_name, const QString &foundry_name, int force_encoding_id, - QtFontDesc *desc, const QList &blacklistedFamilies) + QtFontDesc *desc, const QList &blacklistedFamilies, bool fallback = false) { Q_UNUSED(force_encoding_id); int result = -1; @@ -1132,7 +1132,7 @@ static int match(int script, const QFontDef &request, load(test.family->name, script); // Check if family is supported in the script we want - if (script != QChar::Script_Common && !(test.family->writingSystems[writingSystem] & QtFontFamily::Supported)) + if (!fallback && script != QChar::Script_Common && !(test.family->writingSystems[writingSystem] & QtFontFamily::Supported)) continue; // as we know the script is supported, we can be sure @@ -2450,7 +2450,7 @@ bool QFontDatabase::supportsThreadedFontRendering() */ QFontEngine * QFontDatabase::findFont(int script, const QFontPrivate *fp, - const QFontDef &request, bool multi) + const QFontDef &request, bool multi, bool fallback) { QMutexLocker locker(fontDatabaseMutex()); @@ -2478,7 +2478,7 @@ QFontDatabase::findFont(int script, const QFontPrivate *fp, QtFontDesc desc; QList blackListed; - int index = match(script, request, family_name, foundry_name, force_encoding_id, &desc, blackListed); + int index = match(script, request, family_name, foundry_name, force_encoding_id, &desc, blackListed, fallback); if (index >= 0) { engine = loadEngine(script, request, desc.family, desc.foundry, desc.style, desc.size); if (!engine) diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h index 9986ef6c60..833e574707 100644 --- a/src/gui/text/qfontdatabase.h +++ b/src/gui/text/qfontdatabase.h @@ -160,7 +160,7 @@ private: static void createDatabase(); static void parseFontName(const QString &name, QString &foundry, QString &family); static QString resolveFontFamilyAlias(const QString &family); - static QFontEngine *findFont(int script, const QFontPrivate *fp, const QFontDef &request, bool multi = false); + static QFontEngine *findFont(int script, const QFontPrivate *fp, const QFontDef &request, bool multi = false, bool fallback = false); static void load(const QFontPrivate *d, int script); friend struct QFontDef; diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpa.cpp index f9ed3c38c1..a115d2a901 100644 --- a/src/gui/text/qfontengine_qpa.cpp +++ b/src/gui/text/qfontengine_qpa.cpp @@ -663,7 +663,7 @@ void QFontEngineMultiQPA::loadEngine(int at) request.family = fallbackFamilies.at(at-1); engines[at] = QFontDatabase::findFont(script, /*fontprivate = */0, - request, /*multi = */false); + request, /*multi = */false, true); Q_ASSERT(engines[at]); engines[at]->ref.ref(); engines[at]->fontDef = request; diff --git a/tests/auto/gui/text/qfontdatabase/qfontdatabase.pro b/tests/auto/gui/text/qfontdatabase/qfontdatabase.pro index 6975c4088b..831ed1f572 100644 --- a/tests/auto/gui/text/qfontdatabase/qfontdatabase.pro +++ b/tests/auto/gui/text/qfontdatabase/qfontdatabase.pro @@ -9,3 +9,8 @@ wince* { additionalFiles.path = . DEPLOYMENT += additionalFiles } + +android { + RESOURCES += testdata.qrc +} + diff --git a/tests/auto/gui/text/qfontdatabase/testdata.qrc b/tests/auto/gui/text/qfontdatabase/testdata.qrc new file mode 100644 index 0000000000..8a8670bf17 --- /dev/null +++ b/tests/auto/gui/text/qfontdatabase/testdata.qrc @@ -0,0 +1,5 @@ + + + LED_REAL.TTF + + diff --git a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp index 28db0ba291..2ae12ec246 100644 --- a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp +++ b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp @@ -44,6 +44,8 @@ #include #include #include +#include +#include #include class tst_QFontDatabase : public QObject @@ -77,6 +79,7 @@ private slots: void addAppFont(); void aliases(); + void fallbackFonts(); private: const QString m_testFont; @@ -285,5 +288,26 @@ void tst_QFontDatabase::aliases() QVERIFY(db.hasFamily(alias)); } +void tst_QFontDatabase::fallbackFonts() +{ + QTextLayout layout; + QString s; + s.append(QChar(0x31)); + s.append(QChar(0x05D0)); + layout.setText(s); + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + QList runs = layout.glyphRuns(0, 1); + foreach (QGlyphRun run, runs) { + QRawFont rawFont = run.rawFont(); + QVERIFY(rawFont.isValid()); + + QCOMPARE(run.glyphIndexes().size(), 1); + QVERIFY(run.glyphIndexes().at(0) != 0); + } +} + QTEST_MAIN(tst_QFontDatabase) #include "tst_qfontdatabase.moc" From dddd5ebb087dca47089b14a0cf19f6965f8b09da Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Thu, 10 Jul 2014 14:59:19 +0200 Subject: [PATCH 03/11] Android: enable FBO readback workaround for more devices. Now enabled for all devices equipped with a GPU from the Mali-4xx series or Adreno 2xx series. Task-number: QTBUG-40131 Change-Id: I2923c07033ef768aceec6f5590dbb6f26aa67087 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../platforms/android/qandroidplatformopenglcontext.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp index 3a3ea71562..f27bea8863 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp +++ b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp @@ -72,9 +72,8 @@ bool QAndroidPlatformOpenGLContext::needsFBOReadBackWorkaroud() if (!set) { const char *rendererString = reinterpret_cast(glGetString(GL_RENDERER)); needsWorkaround = - qstrcmp(rendererString, "Mali-400 MP") == 0 - || qstrcmp(rendererString, "Adreno (TM) 200") == 0 - || qstrcmp(rendererString, "Adreno (TM) 205") == 0 + qstrncmp(rendererString, "Mali-4xx", 6) == 0 // Mali-400, Mali-450 + || qstrncmp(rendererString, "Adreno (TM) 2xx", 13) == 0 // Adreno 200, 203, 205 || qstrcmp(rendererString, "GC1000 core") == 0; set = true; } From e899693aa4712fbe53c5c3946ed3da5fad0ea617 Mon Sep 17 00:00:00 2001 From: Ivan Komissarov Date: Thu, 10 Jul 2014 17:56:57 +0400 Subject: [PATCH 04/11] Fixed wrong function name in a file snippet Change-Id: I453c5085685badeb6577009a0c6935dfe384258f Reviewed-by: Richard J. Moore --- src/corelib/doc/snippets/file/file.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/doc/snippets/file/file.cpp b/src/corelib/doc/snippets/file/file.cpp index 0b15360736..5776701283 100644 --- a/src/corelib/doc/snippets/file/file.cpp +++ b/src/corelib/doc/snippets/file/file.cpp @@ -90,7 +90,7 @@ static void writeTextStream_snippet() //! [2] } -static void writeTextStream_snippet() +static void writeDataStream_snippet() { QFile file("out.dat"); if (!file.open(QIODevice::WriteOnly)) From 0cbebb21cc4406059eac19f026e67549a195d089 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 10 Jul 2014 16:09:42 +0200 Subject: [PATCH 05/11] Android: Prefer "Droid Serif" as default serif font I've also updated the qfont test so it passes on Android now. Note that there are no suitable cursive/fantasy fonts on Android, so the regular default "Roboto" (or "Droid Sans" on older devices) will be picked here instead. [ChangeLog][Android] Fixed font selection to prefer "Droid Serif" when Serif style hint is set on QFont. Change-Id: I294eebcc4d79410e435bdddce552acc6044753b2 Reviewed-by: Christian Stromme --- .../org/qtproject/qt5/android/QtActivityDelegate.java | 1 + .../platforms/android/qandroidplatformfontdatabase.cpp | 2 ++ tests/auto/gui/text/qfont/tst_qfont.cpp | 10 +++++----- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index c39bd1a749..8e8b50f737 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -447,6 +447,7 @@ public class QtActivityDelegate m_environmentVariables = loaderParams.getString(ENVIRONMENT_VARIABLES_KEY); String additionalEnvironmentVariables = "QT_ANDROID_FONTS_MONOSPACE=Droid Sans Mono;Droid Sans;Droid Sans Fallback" + + "\tQT_ANDROID_FONTS_SERIF=Droid Serif" + "\tNECESSITAS_API_LEVEL=" + necessitasApiLevel + "\tHOME=" + m_activity.getFilesDir().getAbsolutePath() + "\tTMPDIR=" + m_activity.getFilesDir().getAbsolutePath(); diff --git a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp index fd14f812a0..682a49f6d6 100644 --- a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp +++ b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp @@ -86,6 +86,8 @@ QStringList QAndroidPlatformFontDatabase::fallbacksForFamily(const QString &fami if (styleHint == QFont::Monospace || styleHint == QFont::Courier) return QString(qgetenv("QT_ANDROID_FONTS_MONOSPACE")).split(";") + m_fallbacks[script]; + else if (styleHint == QFont::Serif) + return QString(qgetenv("QT_ANDROID_FONTS_SERIF")).split(";") + m_fallbacks[script]; return QString(qgetenv("QT_ANDROID_FONTS")).split(";") + m_fallbacks[script]; } diff --git a/tests/auto/gui/text/qfont/tst_qfont.cpp b/tests/auto/gui/text/qfont/tst_qfont.cpp index 4c88212c72..995f7a0378 100644 --- a/tests/auto/gui/text/qfont/tst_qfont.cpp +++ b/tests/auto/gui/text/qfont/tst_qfont.cpp @@ -624,11 +624,11 @@ void tst_QFont::defaultFamily_data() QTest::addColumn("styleHint"); QTest::addColumn("acceptableFamilies"); - QTest::newRow("serif") << QFont::Serif << (QStringList() << "Times New Roman" << "Times" << getPlatformGenericFont("serif")); - QTest::newRow("monospace") << QFont::Monospace << (QStringList() << "Courier New" << "Monaco" << getPlatformGenericFont("monospace")); - QTest::newRow("cursive") << QFont::Cursive << (QStringList() << "Comic Sans MS" << "Apple Chancery" << getPlatformGenericFont("cursive")); - QTest::newRow("fantasy") << QFont::Fantasy << (QStringList() << "Impact" << "Zapfino" << getPlatformGenericFont("fantasy")); - QTest::newRow("sans-serif") << QFont::SansSerif << (QStringList() << "Arial" << "Lucida Grande" << getPlatformGenericFont("sans-serif")); + QTest::newRow("serif") << QFont::Serif << (QStringList() << "Times New Roman" << "Times" << "Droid Serif" << getPlatformGenericFont("serif")); + QTest::newRow("monospace") << QFont::Monospace << (QStringList() << "Courier New" << "Monaco" << "Droid Sans Mono" << getPlatformGenericFont("monospace")); + QTest::newRow("cursive") << QFont::Cursive << (QStringList() << "Comic Sans MS" << "Apple Chancery" << "Roboto" << "Droid Sans" << getPlatformGenericFont("cursive")); + QTest::newRow("fantasy") << QFont::Fantasy << (QStringList() << "Impact" << "Zapfino" << "Roboto" << "Droid Sans" << getPlatformGenericFont("fantasy")); + QTest::newRow("sans-serif") << QFont::SansSerif << (QStringList() << "Arial" << "Lucida Grande" << "Roboto" << "Droid Sans" << getPlatformGenericFont("sans-serif")); } void tst_QFont::defaultFamily() From 5c92d21cce18eef9b57f42323b464b6670124c3a Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 16 Jun 2014 14:09:38 +0200 Subject: [PATCH 06/11] xcb: QTabletEvents and proximity events correctly identify the tool The tool is enum TabletDevice reported in QTabletEvent::device(). Each type of tool for each type of tablet has an ID which needs to be mapped to this enum. The meaning of the AbsWheel valuator depends on the tool type: an airbrush sends tangentialPressure in the range -1..+1, whereas an Art Pen (RotationStylus) sends rotation in degrees. Because the evdev driver sends valuator changes individually, we have to store the current value in each TabletData::ValuatorClassInfo to ensure that each QTabletEvent has complete state information. [ChangeLog][Platform Specific Changes][X11 / XCB] QTabletEvents and proximity events correctly identify the tool in use; the meaning of certain valuators depends on the tool; and the valuators' current values are not lost between events Task-number: QTBUG-39666 Task-number: QTBUG-39573 Task-number: QTBUG-39570 Change-Id: I6be242ee57e2ad0848060e04f20c0dd08954a734 Reviewed-by: Frederik Gladhorn --- src/plugins/platforms/xcb/qxcbconnection.h | 9 +- .../platforms/xcb/qxcbconnection_xi2.cpp | 151 +++++++++++++----- 2 files changed, 115 insertions(+), 45 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 0bfc2f8f76..60a4efff4e 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -507,22 +507,25 @@ private: int m_xiOpCode, m_xiEventBase, m_xiErrorBase; #ifndef QT_NO_TABLETEVENT struct TabletData { - TabletData() : deviceId(0), down(false), serialId(0), inProximity(false) { } + TabletData() : deviceId(0), pointerType(QTabletEvent::UnknownPointer), + tool(QTabletEvent::Stylus), down(false), serialId(0), inProximity(false) { } int deviceId; QTabletEvent::PointerType pointerType; + QTabletEvent::TabletDevice tool; bool down; qint64 serialId; bool inProximity; struct ValuatorClassInfo { - ValuatorClassInfo() : minVal(0), maxVal(0) { } + ValuatorClassInfo() : minVal(0.), maxVal(0.), curVal(0.) { } double minVal; double maxVal; + double curVal; int number; }; QHash valuatorInfo; }; bool xi2HandleTabletEvent(void *event, TabletData *tabletData); - void xi2ReportTabletEvent(const TabletData &tabletData, void *event); + void xi2ReportTabletEvent(TabletData &tabletData, void *event); QVector m_tabletData; #endif struct ScrollingDevice { diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index cf809b37e5..e21db89a20 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -685,6 +685,39 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin #endif // XCB_USE_XINPUT21 } +static QTabletEvent::TabletDevice toolIdToTabletDevice(quint32 toolId) { + // keep in sync with wacom_intuos_inout() in Linux kernel driver wacom_wac.c + switch (toolId) { + case 0xd12: + case 0x912: + case 0x112: + case 0x913: /* Intuos3 Airbrush */ + case 0x91b: /* Intuos3 Airbrush Eraser */ + case 0x902: /* Intuos4/5 13HD/24HD Airbrush */ + case 0x90a: /* Intuos4/5 13HD/24HD Airbrush Eraser */ + case 0x100902: /* Intuos4/5 13HD/24HD Airbrush */ + case 0x10090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */ + return QTabletEvent::Airbrush; + case 0x007: /* Mouse 4D and 2D */ + case 0x09c: + case 0x094: + return QTabletEvent::FourDMouse; + case 0x017: /* Intuos3 2D Mouse */ + case 0x806: /* Intuos4 Mouse */ + case 0x096: /* Lens cursor */ + case 0x097: /* Intuos3 Lens cursor */ + case 0x006: /* Intuos4 Lens cursor */ + return QTabletEvent::Puck; + case 0x885: /* Intuos3 Art Pen (Marker Pen) */ + case 0x100804: /* Intuos4/5 13HD/24HD Art Pen */ + case 0x10080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */ + return QTabletEvent::RotationStylus; + case 0: + return QTabletEvent::NoDevice; + } + return QTabletEvent::Stylus; // Safe default assumption if nonzero +} + #ifndef QT_NO_TABLETEVENT bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData) { @@ -713,9 +746,19 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData) xi2ReportTabletEvent(*tabletData, xiEvent); break; case XI_PropertyEvent: { + // This is the wacom driver's way of reporting tool proximity. + // The evdev driver doesn't do it this way. xXIPropertyEvent *ev = reinterpret_cast(event); if (ev->what == XIPropertyModified) { if (ev->property == atom(QXcbAtom::WacomSerialIDs)) { + enum WacomSerialIndex { + _WACSER_USB_ID = 0, + _WACSER_LAST_TOOL_SERIAL, + _WACSER_LAST_TOOL_ID, + _WACSER_TOOL_SERIAL, + _WACSER_TOOL_ID, + _WACSER_COUNT + }; Atom propType; int propFormat; unsigned long numItems, bytesAfter; @@ -723,27 +766,44 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData) if (XIGetProperty(xDisplay, tabletData->deviceId, ev->property, 0, 100, 0, AnyPropertyType, &propType, &propFormat, &numItems, &bytesAfter, &data) == Success) { - if (propType == atom(QXcbAtom::INTEGER) && propFormat == 32) { - int *ptr = reinterpret_cast(data); - for (unsigned long i = 0; i < numItems; ++i) - tabletData->serialId |= qint64(ptr[i]) << (i * 32); + if (propType == atom(QXcbAtom::INTEGER) && propFormat == 32 && numItems == _WACSER_COUNT) { + quint32 *ptr = reinterpret_cast(data); + quint32 tool = ptr[_WACSER_TOOL_ID]; + // Workaround for http://sourceforge.net/p/linuxwacom/bugs/246/ + // e.g. on Thinkpad Helix, tool ID will be 0 and serial will be 1 + if (!tool && ptr[_WACSER_TOOL_SERIAL]) + tool = ptr[_WACSER_TOOL_SERIAL]; + + // The property change event informs us which tool is in proximity or which one left proximity. + if (tool) { + tabletData->inProximity = true; + tabletData->tool = toolIdToTabletDevice(tool); + tabletData->serialId = qint64(ptr[_WACSER_USB_ID]) << 32 | qint64(ptr[_WACSER_TOOL_SERIAL]); + QWindowSystemInterface::handleTabletEnterProximityEvent(tabletData->tool, + tabletData->pointerType, + tabletData->serialId); + } else { + tabletData->inProximity = false; + tabletData->tool = toolIdToTabletDevice(ptr[_WACSER_LAST_TOOL_ID]); + // Workaround for http://sourceforge.net/p/linuxwacom/bugs/246/ + // e.g. on Thinkpad Helix, tool ID will be 0 and serial will be 1 + if (!tabletData->tool) + tabletData->tool = toolIdToTabletDevice(ptr[_WACSER_LAST_TOOL_SERIAL]); + tabletData->serialId = qint64(ptr[_WACSER_USB_ID]) << 32 | qint64(ptr[_WACSER_LAST_TOOL_SERIAL]); + QWindowSystemInterface::handleTabletLeaveProximityEvent(tabletData->tool, + tabletData->pointerType, + tabletData->serialId); + } + if (Q_UNLIKELY(debug_xinput)) { + // TODO maybe have a hash of tabletData->deviceId to device data so we can + // look up the tablet name here, and distinguish multiple tablets + qDebug("XI2 proximity change on tablet %d (USB %x): last tool: %x id %x current tool: %x id %x TabletDevice %d", + ev->deviceid, ptr[_WACSER_USB_ID], ptr[_WACSER_LAST_TOOL_SERIAL], ptr[_WACSER_LAST_TOOL_ID], + ptr[_WACSER_TOOL_SERIAL], ptr[_WACSER_TOOL_ID], tabletData->tool); + } } XFree(data); } - // With recent-enough X drivers this property change event seems to come always - // when entering and leaving proximity. Due to the lack of other options hook up - // the enter/leave events to it. - if (tabletData->inProximity) { - tabletData->inProximity = false; - QWindowSystemInterface::handleTabletLeaveProximityEvent(QTabletEvent::Stylus, - tabletData->pointerType, - tabletData->serialId); - } else { - tabletData->inProximity = true; - QWindowSystemInterface::handleTabletEnterProximityEvent(QTabletEvent::Stylus, - tabletData->pointerType, - tabletData->serialId); - } } } break; @@ -755,7 +815,7 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData) return handled; } -void QXcbConnection::xi2ReportTabletEvent(const TabletData &tabletData, void *event) +void QXcbConnection::xi2ReportTabletEvent(TabletData &tabletData, void *event) { xXIDeviceEvent *ev = reinterpret_cast(event); QXcbWindow *xcbWindow = platformWindowFromId(ev->event); @@ -765,45 +825,52 @@ void QXcbConnection::xi2ReportTabletEvent(const TabletData &tabletData, void *ev const double scale = 65536.0; QPointF local(ev->event_x / scale, ev->event_y / scale); QPointF global(ev->root_x / scale, ev->root_y / scale); - double pressure = 0, rotation = 0; + double pressure = 0, rotation = 0, tangentialPressure = 0; int xTilt = 0, yTilt = 0; - for (QHash::const_iterator it = tabletData.valuatorInfo.constBegin(), - ite = tabletData.valuatorInfo.constEnd(); it != ite; ++it) { + for (QHash::iterator it = tabletData.valuatorInfo.begin(), + ite = tabletData.valuatorInfo.end(); it != ite; ++it) { int valuator = it.key(); - const TabletData::ValuatorClassInfo &classInfo(it.value()); - double value; - if (xi2GetValuatorValueIfSet(event, classInfo.number, &value)) { - double normalizedValue = (value - classInfo.minVal) / double(classInfo.maxVal - classInfo.minVal); - switch (valuator) { - case QXcbAtom::AbsPressure: - pressure = normalizedValue; + TabletData::ValuatorClassInfo &classInfo(it.value()); + xi2GetValuatorValueIfSet(event, classInfo.number, &classInfo.curVal); + double normalizedValue = (classInfo.curVal - classInfo.minVal) / (classInfo.maxVal - classInfo.minVal); + switch (valuator) { + case QXcbAtom::AbsPressure: + pressure = normalizedValue; + break; + case QXcbAtom::AbsTiltX: + xTilt = classInfo.curVal; + break; + case QXcbAtom::AbsTiltY: + yTilt = classInfo.curVal; + break; + case QXcbAtom::AbsWheel: + switch (tabletData.tool) { + case QTabletEvent::Airbrush: + tangentialPressure = normalizedValue * 2.0 - 1.0; // Convert 0..1 range to -1..+1 range break; - case QXcbAtom::AbsTiltX: - xTilt = value; + case QTabletEvent::RotationStylus: + rotation = normalizedValue * 360.0 - 180.0; // Convert 0..1 range to -180..+180 degrees break; - case QXcbAtom::AbsTiltY: - yTilt = value; - break; - case QXcbAtom::AbsWheel: - rotation = value / 64.0; - break; - default: + default: // Other types of styli do not use this valuator break; } + break; + default: + break; } } if (Q_UNLIKELY(debug_xinput)) - qDebug("XI2 tablet event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f pressure %4.2lf tilt %d, %d rotation %6.2lf", - ev->type, ev->sequenceNumber, ev->detail, + qDebug("XI2 event on tablet %d with tool %d type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f pressure %4.2lf tilt %d, %d rotation %6.2lf", + ev->deviceid, tabletData.tool, ev->type, ev->sequenceNumber, ev->detail, fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y), fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y), pressure, xTilt, yTilt, rotation); QWindowSystemInterface::handleTabletEvent(window, tabletData.down, local, global, - QTabletEvent::Stylus, tabletData.pointerType, - pressure, xTilt, yTilt, 0, + tabletData.tool, tabletData.pointerType, + pressure, xTilt, yTilt, tangentialPressure, rotation, 0, tabletData.serialId); } #endif // QT_NO_TABLETEVENT From b6d50e2aa6e6eb08dec6431f94892dcbbba8a213 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Thu, 10 Jul 2014 14:15:28 +0200 Subject: [PATCH 07/11] Doc: edited qtxml.qdocconf Added dependency for Qt Widgets Change-Id: I36fbec0738f5671a07b9dd18fc4487573c560cd2 Reviewed-by: Jerome Pasion --- src/xml/doc/qtxml.qdocconf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xml/doc/qtxml.qdocconf b/src/xml/doc/qtxml.qdocconf index 561d14e528..1e3b534be5 100644 --- a/src/xml/doc/qtxml.qdocconf +++ b/src/xml/doc/qtxml.qdocconf @@ -27,7 +27,7 @@ qhp.QtXml.subprojects.classes.sortPages = true tagfile = ../../../doc/qtxml/qtxml.tags -depends += qtcore qtnetwork qtdoc +depends += qtcore qtnetwork qtdoc qtwidgets headerdirs += .. From d88e4edcd548e5bb024e75016c5a3449d103bd8d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 26 Jun 2014 22:59:19 -0700 Subject: [PATCH 08/11] Work around ICC bug in brace initializations containing constexpr ICC miscompiles this: struct Inner { int i; constexpr Inner(int i) : i(i) {}}; struct Outer { Inner i; }; const Outer x = { -1 }; (Inner = QBasicAtomicInt; Outer = QtPrivate::RefCount, then again for QListData::Data) We expect x to be placed in read-only memory and require no load-time constructor. ICC unfortunately does not do that. By adding a constexpr constructor to Outer, it starts behaving like we expect it to, but falls apart again if you do "const Outer x[]" (the QArrayData statics). The solution is to probably make the varaibles constexpr too, but that's a job for the development branch. Intel issue Id: 6000056211 Intel bug: DPD200534796 Change-Id: Ie9fb5428106486254b7329403890754f300d58c1 Reviewed-by: Thiago Macieira --- src/corelib/global/qcompilerdetection.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index dd880d8ede..b12f944357 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -530,7 +530,8 @@ # define Q_COMPILER_NOEXCEPT # endif # if __INTEL_COMPILER >= 1400 -# define Q_COMPILER_CONSTEXPR +// causes issues with QArrayData and QtPrivate::RefCount - Intel issue ID 6000056211, bug DPD200534796 +//# define Q_COMPILER_CONSTEXPR # define Q_COMPILER_DELEGATING_CONSTRUCTORS # define Q_COMPILER_EXPLICIT_OVERRIDES # define Q_COMPILER_NONSTATIC_MEMBER_INIT From c4b1fffb22e8b20ffe51c5367cdf49eaeada9546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Wed, 23 Apr 2014 15:14:13 +0200 Subject: [PATCH 09/11] Android: Update QSslSocketPrivate::fetchSslCertificateData() Replaces the raw jni calls with our own jni wrappers. This allows us to make use of the centralized cache, avoid global data storage and use a more optimized way to attach to the jni environment. This change also removes the JNI_OnLoad() function since it's not used. If we need to add a JNI_OnLoad() function later, we should find a more suited place for it. Change-Id: Id84ead10c27d03d19c160304b1f9853b381a103c Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../ssl/qsslsocket_openssl_android.cpp | 126 +++--------------- 1 file changed, 16 insertions(+), 110 deletions(-) diff --git a/src/network/ssl/qsslsocket_openssl_android.cpp b/src/network/ssl/qsslsocket_openssl_android.cpp index c7cf03d86d..8cff542e47 100644 --- a/src/network/ssl/qsslsocket_openssl_android.cpp +++ b/src/network/ssl/qsslsocket_openssl_android.cpp @@ -55,126 +55,32 @@ ****************************************************************************/ #include "qsslsocket_openssl_p.h" - - - -#include -#include - -static JavaVM *javaVM = 0; -static jclass appClass; - -static jmethodID getSslCertificatesMethodID; - -struct AttachedJNIEnv -{ - AttachedJNIEnv() - { - attached = false; - if (javaVM->GetEnv((void**)&jniEnv, JNI_VERSION_1_6) < 0) { - if (javaVM->AttachCurrentThread(&jniEnv, NULL) < 0) { - __android_log_print(ANDROID_LOG_ERROR, "Qt", "AttachCurrentThread failed"); - jniEnv = 0; - return; - } - attached = true; - } - } - - ~AttachedJNIEnv() - { - if (attached) - javaVM->DetachCurrentThread(); - } - bool attached; - JNIEnv *jniEnv; -}; - -static const char logTag[] = "Qt"; -static const char classErrorMsg[] = "Can't find class \"%s\""; -static const char methodErrorMsg[] = "Can't find method \"%s%s\""; - - -#define FIND_AND_CHECK_CLASS(CLASS_NAME) \ -clazz = env->FindClass(CLASS_NAME); \ -if (!clazz) { \ - __android_log_print(ANDROID_LOG_FATAL, logTag, classErrorMsg, CLASS_NAME); \ - return JNI_FALSE; \ -} - -#define GET_AND_CHECK_STATIC_METHOD(VAR, CLASS, METHOD_NAME, METHOD_SIGNATURE) \ -VAR = env->GetStaticMethodID(CLASS, METHOD_NAME, METHOD_SIGNATURE); \ -if (!VAR) { \ - __android_log_print(ANDROID_LOG_FATAL, logTag, methodErrorMsg, METHOD_NAME, METHOD_SIGNATURE); \ - return JNI_FALSE; \ -} - -static bool registerNatives(JNIEnv *env) -{ - jclass clazz; - FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/QtNative"); - appClass = static_cast(env->NewGlobalRef(clazz)); - -#if 0 //we don't call C++ functions from Java at this time - if (env->RegisterNatives(appClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) { - __android_log_print(ANDROID_LOG_FATAL, logTag, "RegisterNatives failed"); - return JNI_FALSE; - } -#endif - - GET_AND_CHECK_STATIC_METHOD(getSslCertificatesMethodID, appClass, "getSSLCertificates", "()[[B"); - - return true; -} - -Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) -{ - typedef union { - JNIEnv *nativeEnvironment; - void *venv; - } UnionJNIEnvToVoid; - - __android_log_print(ANDROID_LOG_INFO, logTag, "Network start"); - UnionJNIEnvToVoid uenv; - uenv.venv = NULL; - javaVM = 0; - - if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) { - __android_log_print(ANDROID_LOG_FATAL, logTag, "GetEnv failed"); - return -1; - } - JNIEnv *env = uenv.nativeEnvironment; - if (!registerNatives(env)) { - __android_log_print(ANDROID_LOG_FATAL, logTag, "registerNatives failed"); - return -1; - } - - javaVM = vm; - return JNI_VERSION_1_4; -} +#include QT_BEGIN_NAMESPACE QList QSslSocketPrivate::fetchSslCertificateData() { QList certificateData; - AttachedJNIEnv env; - if (env.jniEnv) { - jobjectArray jcertificates = - static_cast(env.jniEnv->CallStaticObjectMethod(appClass, getSslCertificatesMethodID)); - jint nCertificates = env.jniEnv->GetArrayLength(jcertificates); + QJNIObjectPrivate certificates = QJNIObjectPrivate::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", + "getSSLCertificates", + "()[[B"); + if (!certificates.isValid()) + return certificateData; - for (int i = 0; i < nCertificates; ++i) { - jbyteArray jCert = static_cast(env.jniEnv->GetObjectArrayElement(jcertificates, i)); + QJNIEnvironmentPrivate env; + jobjectArray jcertificates = static_cast(certificates.object()); + const jint nCertificates = env->GetArrayLength(jcertificates); - const uint sz = env.jniEnv->GetArrayLength(jCert); - jbyte *buffer = env.jniEnv->GetByteArrayElements(jCert, 0); - certificateData.append(QByteArray(reinterpret_cast(buffer), sz)); + for (int i = 0; i < nCertificates; ++i) { + jbyteArray jCert = static_cast(env->GetObjectArrayElement(jcertificates, i)); + const uint sz = env->GetArrayLength(jCert); + jbyte *buffer = env->GetByteArrayElements(jCert, 0); + certificateData.append(QByteArray(reinterpret_cast(buffer), sz)); - env.jniEnv->ReleaseByteArrayElements(jCert, buffer, JNI_ABORT); // don't copy back the elements - env.jniEnv->DeleteLocalRef(jCert); - } + env->ReleaseByteArrayElements(jCert, buffer, JNI_ABORT); // don't copy back the elements + env->DeleteLocalRef(jCert); } return certificateData; From 1220a87f8adfcc30cd31a2b1a5bccbee8c394cec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Wed, 23 Apr 2014 16:22:04 +0200 Subject: [PATCH 10/11] Android: Simplify the jni code in QAndroidPlatformServices Remove the use of QtAndroid::AttachedJNIEnv and lazily cache the openURL() methodID on first use. Change-Id: I601d13bc7d644d7cb2f78655ad40c7d9566cf3cb Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../android/qandroidplatformservices.cpp | 21 ++++++------------- .../android/qandroidplatformservices.h | 4 ---- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/plugins/platforms/android/qandroidplatformservices.cpp b/src/plugins/platforms/android/qandroidplatformservices.cpp index 02fe29e576..9c21abe39b 100644 --- a/src/plugins/platforms/android/qandroidplatformservices.cpp +++ b/src/plugins/platforms/android/qandroidplatformservices.cpp @@ -43,30 +43,21 @@ #include #include #include +#include QT_BEGIN_NAMESPACE QAndroidPlatformServices::QAndroidPlatformServices() { - QtAndroid::AttachedJNIEnv env; - if (!env.jniEnv) - return; - - m_openURIMethodID = env.jniEnv->GetStaticMethodID(QtAndroid::applicationClass(), - "openURL", - "(Ljava/lang/String;)V"); } bool QAndroidPlatformServices::openUrl(const QUrl &url) { - QtAndroid::AttachedJNIEnv env; - if (!env.jniEnv) - return false; - - jstring string = env.jniEnv->NewString(reinterpret_cast(url.toString().constData()), - url.toString().length()); - env.jniEnv->CallStaticVoidMethod(QtAndroid::applicationClass(), m_openURIMethodID, string); - env.jniEnv->DeleteLocalRef(string); + QJNIObjectPrivate urlString = QJNIObjectPrivate::fromString(url.toString()); + QJNIObjectPrivate::callStaticMethod(QtAndroid::applicationClass(), + "openURL", + "(Ljava/lang/String;)V", + urlString.object()); return true; } diff --git a/src/plugins/platforms/android/qandroidplatformservices.h b/src/plugins/platforms/android/qandroidplatformservices.h index 08d7773ca4..dd6872b2e9 100644 --- a/src/plugins/platforms/android/qandroidplatformservices.h +++ b/src/plugins/platforms/android/qandroidplatformservices.h @@ -44,7 +44,6 @@ #include #include "androidjnimain.h" -#include QT_BEGIN_NAMESPACE @@ -55,9 +54,6 @@ public: bool openUrl(const QUrl &url); bool openDocument(const QUrl &url); QByteArray desktopEnvironment() const; -private: - jmethodID m_openURIMethodID; - }; QT_END_NAMESPACE From b61ee210e67e5575bc96489908b9c46f7b74ec7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Wed, 23 Apr 2014 16:48:41 +0200 Subject: [PATCH 11/11] Android: Simplify the jni code in QtAndroidClipboard Let the QJNI classes manage the jni environment and cache the jni handles. This lets us lazily cache the jni handle until we actually need them. Change-Id: Iced91e7cab19bdcab8581e94c6f2dd766fed47ed Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../platforms/android/androidjniclipboard.cpp | 68 ++++--------------- .../platforms/android/androidjniclipboard.h | 3 - .../platforms/android/androidjnimain.cpp | 1 - 3 files changed, 12 insertions(+), 60 deletions(-) diff --git a/src/plugins/platforms/android/androidjniclipboard.cpp b/src/plugins/platforms/android/androidjniclipboard.cpp index 87bb08910d..712a384a36 100644 --- a/src/plugins/platforms/android/androidjniclipboard.cpp +++ b/src/plugins/platforms/android/androidjniclipboard.cpp @@ -41,83 +41,39 @@ #include "androidjniclipboard.h" #include "androidjnimain.h" +#include QT_BEGIN_NAMESPACE using namespace QtAndroid; namespace QtAndroidClipboard { - // Clipboard support - static jmethodID m_registerClipboardManagerMethodID = 0; - static jmethodID m_setClipboardTextMethodID = 0; - static jmethodID m_hasClipboardTextMethodID = 0; - static jmethodID m_getClipboardTextMethodID = 0; - // Clipboard support - void setClipboardListener(QAndroidPlatformClipboard *listener) { Q_UNUSED(listener); - - AttachedJNIEnv env; - if (!env.jniEnv) - return; - - env.jniEnv->CallStaticVoidMethod(applicationClass(), m_registerClipboardManagerMethodID); + QJNIObjectPrivate::callStaticMethod(applicationClass(), "registerClipboardManager"); } void setClipboardText(const QString &text) { - AttachedJNIEnv env; - if (!env.jniEnv) - return; - - jstring jtext = env.jniEnv->NewString(reinterpret_cast(text.data()), - text.length()); - env.jniEnv->CallStaticVoidMethod(applicationClass(), m_setClipboardTextMethodID, jtext); - env.jniEnv->DeleteLocalRef(jtext); + QJNIObjectPrivate::callStaticMethod(applicationClass(), + "setClipboardText", + "(Ljava/lang/String;)V", + QJNIObjectPrivate::fromString(text).object()); } bool hasClipboardText() { - AttachedJNIEnv env; - if (!env.jniEnv) - return false; - - return env.jniEnv->CallStaticBooleanMethod(applicationClass(), m_hasClipboardTextMethodID); + return QJNIObjectPrivate::callStaticMethod(applicationClass(), + "hasClipboardText"); } QString clipboardText() { - AttachedJNIEnv env; - if (!env.jniEnv) - return QString(); - - jstring text = reinterpret_cast(env.jniEnv->CallStaticObjectMethod(applicationClass(), - m_getClipboardTextMethodID)); - const jchar *jstr = env.jniEnv->GetStringChars(text, 0); - QString str(reinterpret_cast(jstr), env.jniEnv->GetStringLength(text)); - env.jniEnv->ReleaseStringChars(text, jstr); - return str; - } - - -#define GET_AND_CHECK_STATIC_METHOD(VAR, CLASS, METHOD_NAME, METHOD_SIGNATURE) \ - VAR = env->GetStaticMethodID(CLASS, METHOD_NAME, METHOD_SIGNATURE); \ - if (!VAR) { \ - __android_log_print(ANDROID_LOG_FATAL, qtTagText(), methodErrorMsgFmt(), METHOD_NAME, METHOD_SIGNATURE); \ - return false; \ - } - - bool registerNatives(JNIEnv *env) - { - jclass appClass = QtAndroid::applicationClass(); - - GET_AND_CHECK_STATIC_METHOD(m_registerClipboardManagerMethodID, appClass, "registerClipboardManager", "()V"); - GET_AND_CHECK_STATIC_METHOD(m_setClipboardTextMethodID, appClass, "setClipboardText", "(Ljava/lang/String;)V"); - GET_AND_CHECK_STATIC_METHOD(m_hasClipboardTextMethodID, appClass, "hasClipboardText", "()Z"); - GET_AND_CHECK_STATIC_METHOD(m_getClipboardTextMethodID, appClass, "getClipboardText", "()Ljava/lang/String;"); - - return true; + QJNIObjectPrivate text = QJNIObjectPrivate::callStaticObjectMethod(applicationClass(), + "getClipboardText", + "()Ljava/lang/String;"); + return text.toString(); } } diff --git a/src/plugins/platforms/android/androidjniclipboard.h b/src/plugins/platforms/android/androidjniclipboard.h index 764ef908df..bd833226af 100644 --- a/src/plugins/platforms/android/androidjniclipboard.h +++ b/src/plugins/platforms/android/androidjniclipboard.h @@ -42,7 +42,6 @@ #ifndef ANDROIDJNICLIPBOARD_H #define ANDROIDJNICLIPBOARD_H -#include #include QT_BEGIN_NAMESPACE @@ -56,8 +55,6 @@ namespace QtAndroidClipboard bool hasClipboardText(); QString clipboardText(); // Clipboard support - - bool registerNatives(JNIEnv *env); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index d82487ae9b..3e3e169df9 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -773,7 +773,6 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/) JNIEnv *env = uenv.nativeEnvironment; if (!registerNatives(env) || !QtAndroidInput::registerNatives(env) - || !QtAndroidClipboard::registerNatives(env) || !QtAndroidMenu::registerNatives(env) || !QtAndroidAccessibility::registerNatives(env) || !QtAndroidDialogHelpers::registerNatives(env)) {