From 3f885939c059605a9324a94e488793455c9cd848 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 5 May 2014 08:41:22 +0300 Subject: WinRT: Fix multi-touch on PC The pointer ID was incorrectly interpreted as a device ID, which caused creating a new QTouchDevice for each touch update and potential crashes in QtQuick. The handling has now been simplified and aligned with Windows Phone, treating all touch events as if they originate from the same device. Given that the native device has no ID, it is not possible to track the native device between events anyway (even the pointer values change). Task-number: QTBUG-38745 Change-Id: I24b6c00b765dcb49cd653638afafc04fdd80f774 Reviewed-by: Oliver Wolff Reviewed-by: Maurice Kalinowski --- src/plugins/platforms/winrt/qwinrtscreen.cpp | 81 ++++++++++------------------ src/plugins/platforms/winrt/qwinrtscreen.h | 9 +--- 2 files changed, 31 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 583441f396..b7bfce5931 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -425,17 +425,8 @@ QWinRTScreen::QWinRTScreen(ICoreWindow *window) #endif , m_cursor(new QWinRTCursor(window)) , m_orientation(Qt::PrimaryOrientation) + , m_touchDevice(Q_NULLPTR) { -#ifdef Q_OS_WINPHONE // On phone, there can be only one touch device - QTouchDevice *touchDevice = new QTouchDevice; - touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure); - touchDevice->setType(QTouchDevice::TouchScreen); - touchDevice->setName(QStringLiteral("WinPhoneTouchScreen")); - Pointer pointer = { Pointer::TouchScreen, touchDevice }; - m_pointers.insert(0, pointer); - QWindowSystemInterface::registerTouchDevice(touchDevice); -#endif - Rect rect; window->get_Bounds(&rect); m_geometry = QRect(0, 0, rect.Width, rect.Height); @@ -762,47 +753,25 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a if (FAILED(pointerPoint->get_Properties(&properties))) return E_INVALIDARG; -#ifdef Q_OS_WINPHONE - quint32 pointerId = 0; - Pointer pointer = m_pointers.value(pointerId); + PointerDeviceType pointerDeviceType; +#if defined(Q_OS_WINPHONE) && _MSC_VER <= 1700 + pointerDeviceType = PointerDeviceType_Touch; #else - Pointer pointer = { Pointer::Unknown, 0 }; - quint32 pointerId; - pointerPoint->get_PointerId(&pointerId); - if (m_pointers.contains(pointerId)) { - pointer = m_pointers.value(pointerId); - } else { // We have not yet enumerated this device. Do so now... - IPointerDevice *device; - if (SUCCEEDED(pointerPoint->get_PointerDevice(&device))) { - PointerDeviceType type; - device->get_PointerDeviceType(&type); - switch (type) { - case PointerDeviceType_Touch: - pointer.type = Pointer::TouchScreen; - pointer.device = new QTouchDevice; - pointer.device->setName(QStringLiteral("WinRT TouchScreen ") + QString::number(pointerId)); - // TODO: We may want to probe the device usage flags for more accurate values for these next two - pointer.device->setType(QTouchDevice::TouchScreen); - pointer.device->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure); - QWindowSystemInterface::registerTouchDevice(pointer.device); - break; - - case PointerDeviceType_Pen: - pointer.type = Pointer::Tablet; - break; - - case PointerDeviceType_Mouse: - pointer.type = Pointer::Mouse; - break; - } - - m_pointers.insert(pointerId, pointer); - device->Release(); - } + ComPtr pointerDevice; + HRESULT hr = pointerPoint->get_PointerDevice(&pointerDevice); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get pointer device."); + return S_OK; + } + + hr = pointerDevice->get_PointerDeviceType(&pointerDeviceType); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get pointer device type."); + return S_OK; } #endif - switch (pointer.type) { - case Pointer::Mouse: { + switch (pointerDeviceType) { + case PointerDeviceType_Mouse: { qint32 delta; properties->get_MouseWheelDelta(&delta); if (delta) { @@ -839,7 +808,15 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a break; } - case Pointer::TouchScreen: { + case PointerDeviceType_Touch: { + if (!m_touchDevice) { + m_touchDevice = new QTouchDevice; + m_touchDevice->setName(QStringLiteral("WinRTTouchScreen")); + m_touchDevice->setType(QTouchDevice::TouchScreen); + m_touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure | QTouchDevice::NormalizedPosition); + QWindowSystemInterface::registerTouchDevice(m_touchDevice); + } + quint32 id; pointerPoint->get_PointerId(&id); @@ -867,7 +844,7 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a it.value().normalPosition = QPointF(pos.x()/m_geometry.width(), pos.y()/m_geometry.height()); it.value().pressure = pressure; - QWindowSystemInterface::handleTouchEvent(topWindow(), pointer.device, m_touchPoints.values(), mods); + QWindowSystemInterface::handleTouchEvent(topWindow(), m_touchDevice, m_touchPoints.values(), mods); // Remove released points, station others for (QHash::iterator i = m_touchPoints.begin(); i != m_touchPoints.end();) { @@ -879,7 +856,7 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a break; } - case Pointer::Tablet: { + case PointerDeviceType_Pen: { quint32 id; pointerPoint->get_PointerId(&id); @@ -902,7 +879,7 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a float rotation; properties->get_Twist(&rotation); - QWindowSystemInterface::handleTabletEvent(topWindow(), isPressed, pos, pos, pointerId, + QWindowSystemInterface::handleTabletEvent(topWindow(), isPressed, pos, pos, 0, pointerType, pressure, xTilt, yTilt, 0, rotation, 0, id, mods); diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h index c6511e9446..753d89541c 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.h +++ b/src/plugins/platforms/winrt/qwinrtscreen.h @@ -101,12 +101,6 @@ class QWinRTPageFlipper; class QWinRTCursor; class QWinRTInputContext; -struct Pointer { - enum Type { Unknown, Mouse, TouchScreen, Tablet }; - Type type; - QTouchDevice *device; -}; - class QWinRTScreen : public QPlatformScreen { public: @@ -165,6 +159,7 @@ private: ABI::Windows::UI::Core::ICoreWindow *m_coreWindow; ABI::Windows::UI::ViewManagement::IApplicationViewStatics *m_applicationView; ABI::Windows::ApplicationModel::Core::ICoreApplication *m_application; + QRect m_geometry; QImage::Format m_format; QSurfaceFormat m_surfaceFormat; @@ -183,7 +178,7 @@ private: #ifndef Q_OS_WINPHONE QHash > m_activeKeys; #endif - QHash m_pointers; + QTouchDevice *m_touchDevice; QHash m_touchPoints; }; -- cgit v1.2.3 From b80f732783e43dc21ddbce4b42d9bb61915a3fb6 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 29 Apr 2014 12:32:34 +0200 Subject: Use XI2 event detail to determine changed mouse button The button state part of the XI2 events appears to be badly constructed on some devices and platforms. Even where supported the 'detail' field of the XI2 events is what we should be reading since it indicates the button the event refers to and not just the state of all buttons. Task-number: QTBUG-38169 Change-Id: Iedb7971194b3c27448b72c285a54100c511c17e4 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbconnection.cpp | 13 ------------- src/plugins/platforms/xcb/qxcbconnection.h | 1 - src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 12 ++++++------ 3 files changed, 6 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index e3b81c2b40..f5f6c712c5 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1791,19 +1791,6 @@ bool QXcbConnection::xi2GetValuatorValueIfSet(void *event, int valuatorNum, doub return true; } -bool QXcbConnection::xi2GetButtonState(void *event, int buttonNum) -{ - xXIDeviceEvent *xideviceevent = static_cast(event); - unsigned char *buttonsMaskAddr = (unsigned char*)&xideviceevent[1]; - - for (int i = 0; i < (xideviceevent->buttons_len * 4); i++) { - if (buttonNum < 8) - return (buttonsMaskAddr[i] & (1 << buttonNum)); - buttonNum -= 8; - } - return false; -} - // Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed: // - "pad0" became "extension" // - "pad1" and "pad" became "pad0" diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 1933b89a19..6e511356c4 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -532,7 +532,6 @@ private: #if defined(XCB_USE_XINPUT2) || defined(XCB_USE_XINPUT2_MAEMO) static bool xi2GetValuatorValueIfSet(void *event, int valuatorNum, double *value); static bool xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event, int opCode); - static bool xi2GetButtonState(void *event, int buttonNum); #endif xcb_connection_t *m_connection; diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 831ccba6f6..efa1691780 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -575,7 +575,7 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin #ifdef XCB_USE_XINPUT21 xXIGenericDeviceEvent *xiEvent = reinterpret_cast(event); - if (xiEvent->evtype == XI_Motion) { + if (xiEvent->evtype == XI_Motion && scrollingDevice.orientations) { xXIDeviceEvent* xiDeviceEvent = reinterpret_cast(event); if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) { QPoint rawDelta; @@ -612,20 +612,20 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin QWindowSystemInterface::handleWheelEvent(platformWindow->window(), xiEvent->time, local, global, rawDelta, angleDelta, modifiers); } } - } else if (xiEvent->evtype == XI_ButtonRelease) { + } else if (xiEvent->evtype == XI_ButtonRelease && scrollingDevice.legacyOrientations) { xXIDeviceEvent* xiDeviceEvent = reinterpret_cast(event); if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) { QPoint angleDelta; if (scrollingDevice.legacyOrientations & Qt::Vertical) { - if (xi2GetButtonState(xiDeviceEvent, 4)) + if (xiDeviceEvent->detail == 4) angleDelta.setY(120); - else if (xi2GetButtonState(xiDeviceEvent, 5)) + else if (xiDeviceEvent->detail == 5) angleDelta.setY(-120); } if (scrollingDevice.legacyOrientations & Qt::Horizontal) { - if (xi2GetButtonState(xiDeviceEvent, 6)) + if (xiDeviceEvent->detail == 6) angleDelta.setX(120); - if (xi2GetButtonState(xiDeviceEvent, 7)) + else if (xiDeviceEvent->detail == 7) angleDelta.setX(-120); } if (!angleDelta.isNull()) { -- cgit v1.2.3 From 667f2449a300950e735250c62686c150dab0080d Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Tue, 29 Apr 2014 16:45:33 +0200 Subject: Fix crash on startup when running screenreader MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For exaple Qt Creator would crash when started and a screen reader (eg NVDA) is running. This is due to updateAccessibility being called during the ctor of the TextEdit and on Windows the AT can access properties in the same call resulting in accessing the text control before it's fully constructed. Also make sure to not send accessibility updates for non-widget type edits since we don't support any accessibility in Qt Quick 1. Backported from Qt 5.3.1 since it also crashes Qt Creator on startup on Mac (as soon as accessibility is enabled which may be for various reasons, and basically any app that uses a QTextEdit). Task-number: QTBUG-38659 Task-number: QTBUG-38738 Change-Id: I6e5c0dc47bd75e63fe013a9edadbabccd52c20ee Reviewed-by: Jan Arve Sæther --- src/widgets/widgets/qwidgettextcontrol.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index 9cc62fd10a..54b20e36f5 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -438,7 +438,6 @@ void QWidgetTextControlPrivate::setContent(Qt::TextFormat format, const QString QObject::connect(doc, SIGNAL(contentsChanged()), q, SLOT(_q_updateCurrentCharFormatAndSelection())); QObject::connect(doc, SIGNAL(cursorPositionChanged(QTextCursor)), q, SLOT(_q_emitCursorPosChanged(QTextCursor))); - QObject::connect(doc, SIGNAL(contentsChange(int,int,int)), q, SLOT(_q_contentsChanged(int,int,int))); QObject::connect(doc, SIGNAL(documentLayoutChanged()), q, SLOT(_q_documentLayoutChanged())); // convenience signal forwards @@ -501,6 +500,8 @@ void QWidgetTextControlPrivate::setContent(Qt::TextFormat format, const QString q->ensureCursorVisible(); emit q->cursorPositionChanged(); + + QObject::connect(doc, SIGNAL(contentsChange(int,int,int)), q, SLOT(_q_contentsChanged(int,int,int)), Qt::UniqueConnection); } void QWidgetTextControlPrivate::startDrag() @@ -646,7 +647,8 @@ void QWidgetTextControlPrivate::_q_contentsChanged(int from, int charsRemoved, i { Q_Q(QWidgetTextControl); #ifndef QT_NO_ACCESSIBILITY - if (QAccessible::isActive()) { + + if (QAccessible::isActive() && q->parent() && q->parent()->isWidgetType()) { QTextCursor tmp(doc); tmp.setPosition(from); tmp.setPosition(from + charsAdded, QTextCursor::KeepAnchor); -- cgit v1.2.3 From b6de758ec68a4df87b37d641357770d186022cdf Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 8 May 2014 16:36:51 +0200 Subject: Avoid using repeat on widget textures in eglfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise widgets will not be shown on some embedded systems. Task-number: QTBUG-38866 Change-Id: Id16408dc7eb657c052bbe3bdb86e35ab2f062632 Reviewed-by: Jørgen Lind --- src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp b/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp index 24e9ccd39f..ab92bac37d 100644 --- a/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp @@ -100,9 +100,8 @@ void QEGLPlatformBackingStore::updateTexture() glBindTexture(GL_TEXTURE_2D, m_bsTexture); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - // QOpenGLTextureBlitter requires GL_REPEAT for the time being - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_image.width(), m_image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); } else { glBindTexture(GL_TEXTURE_2D, m_bsTexture); -- cgit v1.2.3 From 0065b55da42b8c6ee0095264b5275fb708887c9d Mon Sep 17 00:00:00 2001 From: Daniel Molkentin Date: Fri, 2 May 2014 00:10:21 +0200 Subject: Ignore expired certificate during certificate validation OpenSSL has a bug when validating a chain with two certificates. If a certificate exists twice (which is a valid use case for renewed CAs), and the first one it hits is expired (which depends on the order on data structure internal to OpenSSL), it will fail to validate the chain. This is only a bandaid fix, which trades improved chain validation for error reporting accuracy. However given that reissuing of CA certs is a real problem that is only getting worse, this fix is needed. See also: https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html#WARNINGS [ChangeLog][QtNetwork][QSslSocket] Added a workaround to an OpenSSL problem that may cause errors when the trust store contains two certificates of the issuing CA, one of which is expired. Task-number: QTBUG-38896 Change-Id: I8f17972ac94555648098624e470fff0eff2e7940 Reviewed-by: Richard J. Moore Reviewed-by: Frederik Gladhorn --- src/network/ssl/qsslcontext.cpp | 23 ++++++++++++----------- src/network/ssl/qsslsocket_openssl.cpp | 24 ++++++++++++------------ 2 files changed, 24 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/network/ssl/qsslcontext.cpp b/src/network/ssl/qsslcontext.cpp index 9c68218062..f5e5352d5e 100644 --- a/src/network/ssl/qsslcontext.cpp +++ b/src/network/ssl/qsslcontext.cpp @@ -214,22 +214,23 @@ init_context: } // Add all our CAs to this store. - QList expiredCerts; foreach (const QSslCertificate &caCertificate, sslContext->sslConfiguration.caCertificates()) { - // add expired certs later, so that the - // valid ones are used before the expired ones - if (caCertificate.expiryDate() < QDateTime::currentDateTime()) { - expiredCerts.append(caCertificate); - } else { + // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html: + // + // If several CA certificates matching the name, key identifier, and + // serial number condition are available, only the first one will be + // examined. This may lead to unexpected results if the same CA + // certificate is available with different expiration dates. If a + // ``certificate expired'' verification error occurs, no other + // certificate will be searched. Make sure to not have expired + // certificates mixed with valid ones. + // + // See also: QSslSocketBackendPrivate::verify() + if (caCertificate.expiryDate() >= QDateTime::currentDateTime()) { q_X509_STORE_add_cert(sslContext->ctx->cert_store, (X509 *)caCertificate.handle()); } } - // now add the expired certs - foreach (const QSslCertificate &caCertificate, expiredCerts) { - q_X509_STORE_add_cert(sslContext->ctx->cert_store, reinterpret_cast(caCertificate.handle())); - } - if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) { // tell OpenSSL the directories where to look up the root certs on demand QList unixDirs = QSslSocketPrivate::unixRootCertDirectories(); diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 1b3928fdfb..45e2fabfe9 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -1598,23 +1598,23 @@ QList QSslSocketBackendPrivate::verify(QList certifi setDefaultCaCertificates(defaultCaCertificates() + systemCaCertificates()); } - QList expiredCerts; - foreach (const QSslCertificate &caCertificate, QSslSocket::defaultCaCertificates()) { - // add expired certs later, so that the - // valid ones are used before the expired ones - if (caCertificate.expiryDate() < QDateTime::currentDateTime()) { - expiredCerts.append(caCertificate); - } else { + // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html: + // + // If several CA certificates matching the name, key identifier, and + // serial number condition are available, only the first one will be + // examined. This may lead to unexpected results if the same CA + // certificate is available with different expiration dates. If a + // ``certificate expired'' verification error occurs, no other + // certificate will be searched. Make sure to not have expired + // certificates mixed with valid ones. + // + // See also: QSslContext::fromConfiguration() + if (caCertificate.expiryDate() >= QDateTime::currentDateTime()) { q_X509_STORE_add_cert(certStore, reinterpret_cast(caCertificate.handle())); } } - // now add the expired certs - foreach (const QSslCertificate &caCertificate, expiredCerts) { - q_X509_STORE_add_cert(certStore, reinterpret_cast(caCertificate.handle())); - } - QMutexLocker sslErrorListMutexLocker(&_q_sslErrorList()->mutex); // Register a custom callback to get all verification errors. -- cgit v1.2.3