diff options
Diffstat (limited to 'src/plugins')
34 files changed, 348 insertions, 623 deletions
diff --git a/src/plugins/generic/tuiotouch/qtuiohandler.cpp b/src/plugins/generic/tuiotouch/qtuiohandler.cpp index 2b42889cb1..4b4d08441f 100644 --- a/src/plugins/generic/tuiotouch/qtuiohandler.cpp +++ b/src/plugins/generic/tuiotouch/qtuiohandler.cpp @@ -129,10 +129,6 @@ void QTuioHandler::processPackets() if (size != datagram.size()) datagram.resize(size); - QOscBundle bundle(datagram); - if (!bundle.isValid()) - continue; - // "A typical TUIO bundle will contain an initial ALIVE message, // followed by an arbitrary number of SET messages that can fit into the // actual bundle capacity and a concluding FSEQ message. A minimal TUIO @@ -140,7 +136,19 @@ void QTuioHandler::processPackets() // messages. The FSEQ frame ID is incremented for each delivered bundle, // while redundant bundles can be marked using the frame sequence ID // -1." - QList<QOscMessage> messages = bundle.messages(); + QList<QOscMessage> messages; + + QOscBundle bundle(datagram); + if (bundle.isValid()) { + messages = bundle.messages(); + } else { + QOscMessage msg(datagram); + if (!msg.isValid()) { + qCWarning(lcTuioSet) << "Got invalid datagram."; + continue; + } + messages.push_back(msg); + } foreach (const QOscMessage &message, messages) { if (message.addressPattern() != "/tuio/2Dcur") { @@ -313,6 +321,14 @@ void QTuioHandler::process2DCurFseq(const QOscMessage &message) Q_UNUSED(message); // TODO: do we need to do anything with the frame id? QWindow *win = QGuiApplication::focusWindow(); + // With TUIO the first application takes exclusive ownership of the "device" + // we cannot attach more than one application to the same port anyway. + // Forcing delivery makes it easy to use simulators in the same machine + // and forget about headaches about unfocused TUIO windows. + static bool forceDelivery = qEnvironmentVariableIsSet("QT_TUIOTOUCH_DELIVER_WITHOUT_FOCUS"); + if (!win && QGuiApplication::topLevelWindows().length() > 0 && forceDelivery) + win = QGuiApplication::topLevelWindows().at(0); + if (!win) return; diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm index 624220ae5e..d2bb3c9cfd 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm @@ -195,6 +195,8 @@ NSString *macSubrole(QAccessibleInterface *interface) QAccessible::State s = interface->state(); if (s.searchEdit) return NSAccessibilitySearchFieldSubrole; + if (s.passwordEdit) + return NSAccessibilitySecureTextFieldSubrole; return nil; } @@ -349,18 +351,23 @@ id getValueAttribute(QAccessibleInterface *interface) const QAccessible::Role qtrole = interface->role(); if (qtrole == QAccessible::EditableText) { if (QAccessibleTextInterface *textInterface = interface->textInterface()) { - // VoiceOver will read out the entire text string at once when returning - // text as a value. For large text edits the size of the returned string - // needs to be limited and text range attributes need to be used instead. - // NSTextEdit returns the first sentence as the value, Do the same here: + int begin = 0; int end = textInterface->characterCount(); - // ### call to textAfterOffset hangs. Booo! - //if (textInterface->characterCount() > 0) - // textInterface->textAfterOffset(0, QAccessible2::SentenceBoundary, &begin, &end); - - QString text = textInterface->text(begin, end); - //qDebug() << "text" << begin << end << text; + QString text; + if (interface->state().passwordEdit) { + // return round password replacement chars + text = QString(end, QChar(kBulletUnicode)); + } else { + // VoiceOver will read out the entire text string at once when returning + // text as a value. For large text edits the size of the returned string + // needs to be limited and text range attributes need to be used instead. + // NSTextEdit returns the first sentence as the value, Do the same here: + // ### call to textAfterOffset hangs. Booo! + //if (textInterface->characterCount() > 0) + // textInterface->textAfterOffset(0, QAccessible2::SentenceBoundary, &begin, &end); + text = textInterface->text(begin, end); + } return QCFString::toNSString(text); } } diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp index 40709fc3d0..f12649e55e 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp @@ -63,6 +63,10 @@ QWindowsDirect2DPaintDevice::QWindowsDirect2DPaintDevice(QWindowsDirect2DBitmap { } +QWindowsDirect2DPaintDevice::~QWindowsDirect2DPaintDevice() +{ +} + QPaintEngine *QWindowsDirect2DPaintDevice::paintEngine() const { Q_D(const QWindowsDirect2DPaintDevice); diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h index 702fd4178c..08fcbba015 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h @@ -50,6 +50,8 @@ class QWindowsDirect2DPaintDevice : public QPaintDevice public: QWindowsDirect2DPaintDevice(QWindowsDirect2DBitmap *bitmap, QInternal::PaintDeviceFlags flags, QWindowsDirect2DPaintEngine::Flags paintFlags = QWindowsDirect2DPaintEngine::NoFlag); + ~QWindowsDirect2DPaintDevice(); + QPaintEngine *paintEngine() const Q_DECL_OVERRIDE; int devType() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp index f7450708ab..5c7b9fe96d 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp @@ -301,8 +301,13 @@ void QEglFSKmsEglDeviceIntegration::waitForVSync(QPlatformSurface *) const if (currentMode) drmModeFreeCrtc(currentMode); if (alreadySet) { - qCDebug(qLcEglfsKmsDebug, "Mode already set"); - return; + // Maybe detecting the DPMS mode could help here, but there are no properties + // exposed on the connector apparently. So rely on an env var for now. + static bool alwaysDoSet = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ALWAYS_SET_MODE"); + if (!alwaysDoSet) { + qCDebug(qLcEglfsKmsDebug, "Mode already set"); + return; + } } qCDebug(qLcEglfsKmsDebug, "Setting mode"); diff --git a/src/plugins/platforms/windows/accessible/comutils.cpp b/src/plugins/platforms/windows/accessible/comutils.cpp index 8ad732b0e7..94e56e8b73 100644 --- a/src/plugins/platforms/windows/accessible/comutils.cpp +++ b/src/plugins/platforms/windows/accessible/comutils.cpp @@ -272,348 +272,6 @@ bool QVariant2VARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeN } } break; -#if 0 // not a value with min/max semantics - case QVariant::Font: - if (out && arg.vt == (VT_DISPATCH|VT_BYREF)) { - if (*arg.ppdispVal) - (*arg.ppdispVal)->Release(); - *arg.ppdispVal = QFontToIFont(qvariant_cast<QFont>(qvar)); - } else { - arg.vt = VT_DISPATCH; - arg.pdispVal = QFontToIFont(qvariant_cast<QFont>(qvar)); - if (out) { - arg.ppdispVal = new IDispatch*(arg.pdispVal); - arg.vt |= VT_BYREF; - } - } - break; - case QVariant::Pixmap: - if (out && arg.vt == (VT_DISPATCH|VT_BYREF)) { - if (*arg.ppdispVal) - (*arg.ppdispVal)->Release(); - *arg.ppdispVal = QPixmapToIPicture(qvariant_cast<QPixmap>(qvar)); - } else { - arg.vt = VT_DISPATCH; - arg.pdispVal = QPixmapToIPicture(qvariant_cast<QPixmap>(qvar)); - if (out) { - arg.ppdispVal = new IDispatch*(arg.pdispVal); - arg.vt |= VT_BYREF; - } - } - break; - case QVariant::Cursor: - { -#ifndef QT_NO_CURSOR - int shape = qvariant_cast<QCursor>(qvar).shape(); - if (out && (arg.vt & VT_BYREF)) { - switch (arg.vt & ~VT_BYREF) { - case VT_I4: - *arg.plVal = shape; - break; - case VT_I2: - *arg.piVal = shape; - break; - case VT_UI4: - *arg.pulVal = shape; - break; - case VT_UI2: - *arg.puiVal = shape; - break; - case VT_INT: - *arg.pintVal = shape; - break; - case VT_UINT: - *arg.puintVal = shape; - break; - } - } else { - arg.vt = VT_I4; - arg.lVal = shape; - if (out) { - arg.plVal = new long(arg.lVal); - arg.vt |= VT_BYREF; - } - } -#endif - } - break; - - case QVariant::List: - { - const QList<QVariant> list = qvar.toList(); - const int count = list.count(); - VARTYPE vt = VT_VARIANT; - QVariant::Type listType = QVariant::LastType; // == QVariant - if (!typeName.isEmpty() && typeName.startsWith("QList<")) { - const QByteArray listTypeName = typeName.mid(6, typeName.length() - 7); // QList<int> -> int - listType = QVariant::nameToType(listTypeName); - } - - VARIANT variant; - void *pElement = &variant; - switch (listType) { - case QVariant::Int: - vt = VT_I4; - pElement = &variant.lVal; - break; - case QVariant::Double: - vt = VT_R8; - pElement = &variant.dblVal; - break; - case QVariant::DateTime: - vt = VT_DATE; - pElement = &variant.date; - break; - case QVariant::Bool: - vt = VT_BOOL; - pElement = &variant.boolVal; - break; - case QVariant::LongLong: -#if !defined(Q_OS_WINCE) && defined(_MSC_VER) && _MSC_VER >= 1400 - vt = VT_I8; - pElement = &variant.llVal; -#else - vt = VT_CY; - pElement = &variant.cyVal; -#endif - break; - default: - break; - } - SAFEARRAY *array = 0; - bool is2D = false; - // If the first element in the array is a list the whole list is - // treated as a 2D array. The column count is taken from the 1st element. - if (count) { - QVariantList col = list.at(0).toList(); - int maxColumns = col.count(); - if (maxColumns) { - is2D = true; - SAFEARRAYBOUND rgsabound[2] = { {0} }; - rgsabound[0].cElements = count; - rgsabound[1].cElements = maxColumns; - array = SafeArrayCreate(VT_VARIANT, 2, rgsabound); - LONG rgIndices[2]; - for (LONG i = 0; i < count; ++i) { - rgIndices[0] = i; - QVariantList columns = list.at(i).toList(); - int columnCount = qMin(maxColumns, columns.count()); - for (LONG j = 0; j < columnCount; ++j) { - QVariant elem = columns.at(j); - VariantInit(&variant); - QVariant2VARIANT(elem, variant, elem.typeName()); - rgIndices[1] = j; - SafeArrayPutElement(array, rgIndices, pElement); - clearVARIANT(&variant); - } - } - - } - } - if (!is2D) { - array = SafeArrayCreateVector(vt, 0, count); - for (LONG index = 0; index < count; ++index) { - QVariant elem = list.at(index); - if (listType != QVariant::LastType) - elem.convert(listType); - VariantInit(&variant); - QVariant2VARIANT(elem, variant, elem.typeName()); - SafeArrayPutElement(array, &index, pElement); - clearVARIANT(&variant); - } - } - if (out && arg.vt == (VT_ARRAY|vt|VT_BYREF)) { - if (*arg.pparray) - SafeArrayDestroy(*arg.pparray); - *arg.pparray = array; - } else { - arg.vt = VT_ARRAY|vt; - arg.parray = array; - if (out) { - arg.pparray = new SAFEARRAY*(arg.parray); - arg.vt |= VT_BYREF; - } - } - } - break; - - case QVariant::StringList: - { - const QStringList list = qvar.toStringList(); - const int count = list.count(); - SAFEARRAY *array = SafeArrayCreateVector(VT_BSTR, 0, count); - for (LONG index = 0; index < count; ++index) { - QString elem = list.at(index); - BSTR bstr = QStringToBSTR(elem); - SafeArrayPutElement(array, &index, bstr); - SysFreeString(bstr); - } - - if (out && arg.vt == (VT_ARRAY|VT_BSTR|VT_BYREF)) { - if (*arg.pparray) - SafeArrayDestroy(*arg.pparray); - *arg.pparray = array; - } else { - arg.vt = VT_ARRAY|VT_BSTR; - arg.parray = array; - if (out) { - arg.pparray = new SAFEARRAY*(arg.parray); - arg.vt |= VT_BYREF; - } - } - } - break; - - case QVariant::ByteArray: - { - const QByteArray bytes = qvar.toByteArray(); - const uint count = bytes.count(); - SAFEARRAY *array = SafeArrayCreateVector(VT_UI1, 0, count); - if (count) { - const char *data = bytes.constData(); - char *dest; - SafeArrayAccessData(array, (void **)&dest); - memcpy(dest, data, count); - SafeArrayUnaccessData(array); - } - - if (out && arg.vt == (VT_ARRAY|VT_UI1|VT_BYREF)) { - if (*arg.pparray) - SafeArrayDestroy(*arg.pparray); - *arg.pparray = array; - } else { - arg.vt = VT_ARRAY|VT_UI1; - arg.parray = array; - if (out) { - arg.pparray = new SAFEARRAY*(arg.parray); - arg.vt |= VT_BYREF; - } - } - } - break; - -#ifdef QAX_SERVER - case QVariant::Rect: - case QVariant::Size: - case QVariant::Point: - { - typedef HRESULT(WINAPI* PGetRecordInfoFromTypeInfo)(ITypeInfo *, IRecordInfo **); - static PGetRecordInfoFromTypeInfo pGetRecordInfoFromTypeInfo = 0; - static bool resolved = false; - if (!resolved) { - QSystemLibrary oleaut32(QLatin1String("oleaut32")); - pGetRecordInfoFromTypeInfo = (PGetRecordInfoFromTypeInfo)oleaut32.resolve("GetRecordInfoFromTypeInfo"); - resolved = true; - } - if (!pGetRecordInfoFromTypeInfo) - break; - - ITypeInfo *typeInfo = 0; - IRecordInfo *recordInfo = 0; - CLSID clsid = qvar.type() == QVariant::Rect ? CLSID_QRect - :qvar.type() == QVariant::Size ? CLSID_QSize - :CLSID_QPoint; - qAxTypeLibrary->GetTypeInfoOfGuid(clsid, &typeInfo); - if (!typeInfo) - break; - pGetRecordInfoFromTypeInfo(typeInfo, &recordInfo); - typeInfo->Release(); - if (!recordInfo) - break; - - void *record = 0; - switch (qvar.type()) { - case QVariant::Rect: - { - QRect qrect(qvar.toRect()); - recordInfo->RecordCreateCopy(&qrect, &record); - } - break; - case QVariant::Size: - { - QSize qsize(qvar.toSize()); - recordInfo->RecordCreateCopy(&qsize, &record); - } - break; - case QVariant::Point: - { - QPoint qpoint(qvar.toPoint()); - recordInfo->RecordCreateCopy(&qpoint, &record); - } - break; - } - - arg.vt = VT_RECORD; - arg.pRecInfo = recordInfo, - arg.pvRecord = record; - if (out) { - qWarning("QVariant2VARIANT: out-parameter not supported for records"); - return false; - } - } - break; -#endif // QAX_SERVER - case QVariant::UserType: - { - QByteArray subType = qvar.typeName(); -#ifdef QAX_SERVER - if (subType.endsWith('*')) - subType.truncate(subType.length() - 1); -#endif - if (!qstrcmp(qvar.typeName(), "IDispatch*")) { - arg.vt = VT_DISPATCH; - arg.pdispVal = *(IDispatch**)qvar.data(); - if (arg.pdispVal) - arg.pdispVal->AddRef(); - if (out) { - qWarning("QVariant2VARIANT: out-parameter not supported for IDispatch"); - return false; - } - } else if (!qstrcmp(qvar.typeName(), "IDispatch**")) { - arg.vt = VT_DISPATCH; - arg.ppdispVal = *(IDispatch***)qvar.data(); - if (out) - arg.vt |= VT_BYREF; - } else if (!qstrcmp(qvar.typeName(), "IUnknown*")) { - arg.vt = VT_UNKNOWN; - arg.punkVal = *(IUnknown**)qvar.data(); - if (arg.punkVal) - arg.punkVal->AddRef(); - if (out) { - qWarning("QVariant2VARIANT: out-parameter not supported for IUnknown"); - return false; - } -#ifdef QAX_SERVER - } else if (qAxFactory()->metaObject(QString::fromLatin1(subType.constData()))) { - arg.vt = VT_DISPATCH; - void *user = *(void**)qvar.constData(); -// qVariantGet(qvar, user, qvar.typeName()); - if (!user) { - arg.pdispVal = 0; - } else { - qAxFactory()->createObjectWrapper(static_cast<QObject*>(user), &arg.pdispVal); - } - if (out) { - qWarning("QVariant2VARIANT: out-parameter not supported for subtype"); - return false; - } -#else - } else if (QMetaType::type(subType)) { - QAxObject *object = *(QAxObject**)qvar.constData(); -// qVariantGet(qvar, object, subType); - arg.vt = VT_DISPATCH; - object->queryInterface(IID_IDispatch, (void**)&arg.pdispVal); - if (out) { - qWarning("QVariant2VARIANT: out-parameter not supported for subtype"); - return false; - } -#endif - } else { - return false; - } - } - break; -#endif case QVariant::Invalid: // default-parameters not set if (out && arg.vt == (VT_ERROR|VT_BYREF)) { diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index 5ed8d30e67..9531272a07 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -1699,12 +1699,12 @@ QByteArray QWindowsIA2Accessible::IIDToString(REFIID id) } // Q_STATIC_ASSERT(IA2_ROLE_CANVAS == QAccessible::Canvas); // ### Qt 6: make them the same -Q_STATIC_ASSERT(IA2_ROLE_COLOR_CHOOSER == QAccessible::ColorChooser); -Q_STATIC_ASSERT(IA2_ROLE_FOOTER == QAccessible::Footer); -Q_STATIC_ASSERT(IA2_ROLE_FORM == QAccessible::Form); -Q_STATIC_ASSERT(IA2_ROLE_HEADING == QAccessible::Heading); -Q_STATIC_ASSERT(IA2_ROLE_NOTE == QAccessible::Note); -Q_STATIC_ASSERT(IA2_ROLE_COMPLEMENTARY_CONTENT == QAccessible::ComplementaryContent); +Q_STATIC_ASSERT(IA2_ROLE_COLOR_CHOOSER == static_cast<IA2Role>(QAccessible::ColorChooser)); +Q_STATIC_ASSERT(IA2_ROLE_FOOTER == static_cast<IA2Role>(QAccessible::Footer)); +Q_STATIC_ASSERT(IA2_ROLE_FORM == static_cast<IA2Role>(QAccessible::Form)); +Q_STATIC_ASSERT(IA2_ROLE_HEADING == static_cast<IA2Role>(QAccessible::Heading)); +Q_STATIC_ASSERT(IA2_ROLE_NOTE == static_cast<IA2Role>(QAccessible::Note)); +Q_STATIC_ASSERT(IA2_ROLE_COMPLEMENTARY_CONTENT == static_cast<IA2Role>(QAccessible::ComplementaryContent)); QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp index 0437290dcb..cdadb070a5 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp @@ -219,24 +219,6 @@ IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc) #endif // defined(Q_OS_WINCE) } -/* -void QWindowsAccessibility::setRootObject(QObject *o) -{ - -} - -void QWindowsAccessibility::initialize() -{ - -} - -void QWindowsAccessibility::cleanup() -{ - -} - -*/ - bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult) { #if !defined(Q_OS_WINCE) @@ -245,12 +227,10 @@ bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, W } else if ((DWORD)lParam == DWORD(OBJID_CLIENT)) { // Start handling accessibility internally QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true); -#if 1 // Ignoring all requests while starting up // ### Maybe QPA takes care of this??? if (QCoreApplication::startingUp() || QCoreApplication::closingDown()) return false; -#endif typedef LRESULT (WINAPI *PtrLresultFromObject)(REFIID, WPARAM, LPUNKNOWN); static PtrLresultFromObject ptrLresultFromObject = 0; diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h index a7113d4f68..5faf80f829 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h +++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h @@ -47,12 +47,7 @@ class QWindowsAccessibility : public QPlatformAccessibility public: QWindowsAccessibility(); static bool handleAccessibleObjectFromWindowRequest(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult); - virtual void notifyAccessibilityUpdate(QAccessibleEvent *event); - /* - virtual void setRootObject(QObject *o); - virtual void initialize(); - virtual void cleanup(); - */ + void notifyAccessibilityUpdate(QAccessibleEvent *event) Q_DECL_OVERRIDE; static IAccessible *wrap(QAccessibleInterface *acc); static QWindow *windowHelper(const QAccessibleInterface *iface); }; diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp index 1071a2e038..8b0be5d916 100644 --- a/src/plugins/platforms/windows/qwindowsclipboard.cpp +++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp @@ -51,9 +51,6 @@ QT_BEGIN_NAMESPACE -static const char formatTextPlainC[] = "text/plain"; -static const char formatTextHtmlC[] = "text/html"; - /*! \class QWindowsClipboard \brief Clipboard implementation. diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 4934b6c6e4..6ff6875c49 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -89,20 +89,6 @@ Q_LOGGING_CATEGORY(lcQpaAccessibility, "qt.qpa.accessibility") int QWindowsContext::verbose = 0; -// Get verbosity of components from "foo:2,bar:3" -static inline int componentVerbose(const char *v, const char *keyWord) -{ - if (const char *k = strstr(v, keyWord)) { - k += qstrlen(keyWord); - if (*k == ':') { - ++k; - if (isdigit(*k)) - return *k - '0'; - } - } - return 0; -} - #if !defined(LANG_SYRIAC) # define LANG_SYRIAC 0x5a #endif diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index c769eb04a4..9f65f73a81 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -142,8 +142,8 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits, QScopedArrayPointer<uchar> xMask(new uchar[height * n]); int x = 0; for (int i = 0; i < height; ++i) { - const uchar *bits = bbits.scanLine(i); - const uchar *mask = mbits.scanLine(i); + const uchar *bits = bbits.constScanLine(i); + const uchar *mask = mbits.constScanLine(i); for (int j = 0; j < n; ++j) { uchar b = bits[j]; uchar m = mask[j]; @@ -173,8 +173,8 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits, x += sysN; } else { int fillWidth = n > sysN ? sysN : n; - const uchar *bits = bbits.scanLine(i); - const uchar *mask = mbits.scanLine(i); + const uchar *bits = bbits.constScanLine(i); + const uchar *mask = mbits.constScanLine(i); for (int j = 0; j < fillWidth; ++j) { uchar b = bits[j]; uchar m = mask[j]; @@ -246,9 +246,10 @@ static QSize systemCursorSize(const QPlatformScreen *screen = Q_NULLPTR) return primaryScreenCursorSize; } +#if defined (Q_OS_WINCE) || defined (QT_NO_IMAGEFORMAT_PNG) + static inline QSize standardCursorSize() { return QSize(32, 32); } -#if defined (Q_OS_WINCE) || defined (QT_NO_IMAGEFORMAT_PNG) // Create pixmap cursors from data and scale the image if the cursor size is // higher than the standard 32. Note that bitmap cursors as produced by // createBitmapCursor() only work for standard sizes (32,48,64...), which does diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 9211fd1320..2d75e1720a 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -737,7 +737,7 @@ inline QUrl QWindowsFileDialogSharedData::directory() const inline void QWindowsFileDialogSharedData::setDirectory(const QUrl &d) { - QMutexLocker (&m_data->mutex); + QMutexLocker locker(&m_data->mutex); m_data->directory = d; } @@ -751,7 +751,7 @@ inline QString QWindowsFileDialogSharedData::selectedNameFilter() const inline void QWindowsFileDialogSharedData::setSelectedNameFilter(const QString &f) { - QMutexLocker (&m_data->mutex); + QMutexLocker locker(&m_data->mutex); m_data->selectedNameFilter = f; } @@ -771,13 +771,13 @@ inline QString QWindowsFileDialogSharedData::selectedFile() const inline void QWindowsFileDialogSharedData::setSelectedFiles(const QList<QUrl> &urls) { - QMutexLocker (&m_data->mutex); + QMutexLocker locker(&m_data->mutex); m_data->selectedFiles = urls; } inline void QWindowsFileDialogSharedData::fromOptions(const QSharedPointer<QFileDialogOptions> &o) { - QMutexLocker (&m_data->mutex); + QMutexLocker locker(&m_data->mutex); m_data->directory = o->initialDirectory(); m_data->selectedFiles = o->initiallySelectedFiles(); m_data->selectedNameFilter = o->initiallySelectedNameFilter(); @@ -1584,11 +1584,6 @@ QWindowsNativeFileDialogBase *QWindowsNativeFileDialogBase::create(QFileDialogOp return result; } -static inline bool isQQuickWindow(const QWindow *w = 0) -{ - return w && w->inherits("QQuickWindow"); -} - /*! \class QWindowsFileDialogHelper \brief Helper for native Windows file dialogs @@ -1604,8 +1599,8 @@ class QWindowsFileDialogHelper : public QWindowsDialogHelperBase<QPlatformFileDi { public: QWindowsFileDialogHelper() {} - virtual bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const { return false; } - virtual bool defaultNameFilterDisables() const + virtual bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const Q_DECL_OVERRIDE { return false; } + virtual bool defaultNameFilterDisables() const Q_DECL_OVERRIDE { return false; } virtual void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE; virtual QUrl directory() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.h b/src/plugins/platforms/windows/qwindowsdialoghelpers.h index e0474fc456..2bc823452a 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.h +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.h @@ -64,9 +64,9 @@ public: ~QWindowsDialogHelperBase() { cleanupThread(); } void exec() Q_DECL_OVERRIDE; - virtual bool show(Qt::WindowFlags windowFlags, + bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, - QWindow *parent); + QWindow *parent) Q_DECL_OVERRIDE; void hide() Q_DECL_OVERRIDE; virtual bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const { return true; } @@ -75,7 +75,7 @@ protected: QWindowsDialogHelperBase(); QWindowsNativeDialogBase *nativeDialog() const; inline bool hasNativeDialog() const { return m_nativeDialog; } - void timerEvent(QTimerEvent *); + void timerEvent(QTimerEvent *) Q_DECL_OVERRIDE; private: virtual QWindowsNativeDialogBase *createNativeDialog() = 0; diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 65a9763be6..5983741711 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -342,8 +342,8 @@ bool QWindowsLibGLESv2::init() return glBindTexture && glCreateShader && glClearDepthf; } -QWindowsEGLStaticContext::QWindowsEGLStaticContext(EGLDisplay display, int version) - : m_display(display), m_version(version) +QWindowsEGLStaticContext::QWindowsEGLStaticContext(EGLDisplay display) + : m_display(display) { } @@ -410,7 +410,7 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester: } qCDebug(lcQpaGl) << __FUNCTION__ << "Created EGL display" << display << 'v' <<major << '.' << minor; - return new QWindowsEGLStaticContext(display, (major << 8) | minor); + return new QWindowsEGLStaticContext(display); } QWindowsEGLStaticContext::~QWindowsEGLStaticContext() @@ -990,7 +990,7 @@ EGLConfig QWindowsEGLContext::chooseConfig(const QSurfaceFormat &format) QVector<EGLConfig> configs(matching); QWindowsEGLStaticContext::libEGL.eglChooseConfig(display, configureAttributes.constData(), configs.data(), configs.size(), &matching); if (!cfg && matching > 0) - cfg = configs.first(); + cfg = configs.constFirst(); EGLint red = 0; EGLint green = 0; diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h index 555d633a78..6945939941 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.h +++ b/src/plugins/platforms/windows/qwindowseglcontext.h @@ -257,9 +257,9 @@ public: EGLDisplay display() const { return m_display; } - QWindowsOpenGLContext *createContext(QOpenGLContext *context); - void *moduleHandle() const { return libGLESv2.moduleHandle(); } - QOpenGLContext::OpenGLModuleType moduleType() const { return QOpenGLContext::LibGLES; } + QWindowsOpenGLContext *createContext(QOpenGLContext *context) Q_DECL_OVERRIDE; + void *moduleHandle() const Q_DECL_OVERRIDE { return libGLESv2.moduleHandle(); } + QOpenGLContext::OpenGLModuleType moduleType() const Q_DECL_OVERRIDE { return QOpenGLContext::LibGLES; } void *createWindowSurface(void *nativeWindow, void *nativeConfig, int *err) Q_DECL_OVERRIDE; void destroyWindowSurface(void *nativeSurface) Q_DECL_OVERRIDE; @@ -270,10 +270,9 @@ public: static QWindowsLibGLESv2 libGLESv2; private: - QWindowsEGLStaticContext(EGLDisplay display, int version); + explicit QWindowsEGLStaticContext(EGLDisplay display); const EGLDisplay m_display; - const int m_version; //! majorVersion<<8 + minorVersion }; class QWindowsEGLContext : public QWindowsOpenGLContext diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp index 684c44acf2..88ceb37693 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp @@ -454,6 +454,8 @@ static bool addFontToDatabase(const QString &faceName, const FontKey *key = findFontKey(faceName, &index); if (!key) { key = findFontKey(fullName, &index); + if (!key && !registerAlias && englishName.isEmpty() && localizedName(faceName)) + englishName = getEnglishName(faceName); if (!key && !englishName.isEmpty()) key = findFontKey(englishName, &index); if (!key) diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp index bf62052ee5..00f9ecea60 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.cpp +++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp @@ -103,17 +103,6 @@ static void resolveGetCharWidthI() ptrGetCharWidthI = (PtrGetCharWidthI)QSystemLibrary::resolve(QStringLiteral("gdi32"), "GetCharWidthI"); } -static inline quint32 getUInt(unsigned char *p) -{ - quint32 val; - val = *p++ << 24; - val |= *p++ << 16; - val |= *p++ << 8; - val |= *p; - - return val; -} - static inline quint16 getUShort(unsigned char *p) { quint16 val; @@ -265,7 +254,6 @@ QWindowsFontEngine::QWindowsFontEngine(const QString &name, m_logfont(lf), ttf(0), hasOutline(0), - lw(0), cmap(0), cmapSize(0), lbearing(SHRT_MIN), @@ -1161,7 +1149,9 @@ glyph_metrics_t QWindowsFontEngine::alphaMapBoundingBox(glyph_t glyph, QFixed, c QImage QWindowsFontEngine::alphaMapForGlyph(glyph_t glyph, const QTransform &xform) { HFONT font = hfont; - if (m_fontEngineData->clearTypeEnabled) { + + bool clearTypeTemporarilyDisabled = (m_fontEngineData->clearTypeEnabled && m_logfont.lfQuality != NONANTIALIASED_QUALITY); + if (clearTypeTemporarilyDisabled) { LOGFONT lf = m_logfont; lf.lfQuality = ANTIALIASED_QUALITY; font = CreateFontIndirect(&lf); @@ -1184,11 +1174,11 @@ QImage QWindowsFontEngine::alphaMapForGlyph(glyph_t glyph, const QTransform &xfo for (int y=0; y<mask->height(); ++y) { uchar *dest = alphaMap.scanLine(y); if (mask->image().format() == QImage::Format_RGB16) { - const qint16 *src = (qint16 *) ((const QImage &) mask->image()).scanLine(y); + const qint16 *src = reinterpret_cast<const qint16 *>(mask->image().constScanLine(y)); for (int x=0; x<mask->width(); ++x) dest[x] = 255 - qGray(src[x]); } else { - const uint *src = (uint *) ((const QImage &) mask->image()).scanLine(y); + const uint *src = reinterpret_cast<const uint *>(mask->image().constScanLine(y)); for (int x=0; x<mask->width(); ++x) { if (QWindowsNativeImage::systemFormat() == QImage::Format_RGB16) dest[x] = 255 - qGray(src[x]); @@ -1200,7 +1190,7 @@ QImage QWindowsFontEngine::alphaMapForGlyph(glyph_t glyph, const QTransform &xfo // Cleanup... delete mask; - if (m_fontEngineData->clearTypeEnabled) { + if (clearTypeTemporarilyDisabled) { DeleteObject(font); } @@ -1233,7 +1223,7 @@ QImage QWindowsFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed, const QTra QImage rgbMask(mask->width(), mask->height(), QImage::Format_RGB32); for (int y=0; y<mask->height(); ++y) { uint *dest = (uint *) rgbMask.scanLine(y); - const uint *src = (uint *) source.scanLine(y); + const uint *src = reinterpret_cast<const uint *>(source.constScanLine(y)); for (int x=0; x<mask->width(); ++x) { dest[x] = 0xffffffff - (0x00ffffff & src[x]); } diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h index 5317368455..47891a2830 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.h +++ b/src/plugins/platforms/windows/qwindowsfontengine.h @@ -144,7 +144,6 @@ private: uint hasUnreliableOutline : 1; uint cffTable : 1; TEXTMETRIC tm; - int lw; const unsigned char *cmap; int cmapSize; QByteArray cmapTable; diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index d99a6caecd..a7de0e1783 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -493,7 +493,7 @@ QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed sub QImage alphaMap(im.width(), im.height(), QImage::Format_Alpha8); for (int y=0; y<im.height(); ++y) { - uint *src = (uint*) im.scanLine(y); + const uint *src = reinterpret_cast<const uint *>(im.constScanLine(y)); uchar *dst = alphaMap.scanLine(y); for (int x=0; x<im.width(); ++x) { *dst = 255 - (m_fontEngineData->pow_gamma[qGray(0xffffffff - *src)] * 255. / 2047.); diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index c5dff60114..b7e7867404 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -614,10 +614,6 @@ static inline int asciiToKeycode(char a, int state) return a & 0xff; } -static inline bool isModifierKey(int code) -{ - return (code >= Qt::Key_Shift) && (code <= Qt::Key_ScrollLock); -} // Key translation -----------------------------------------------------------------------[ end ]--- diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index eaaf2820ee..a8264b55c0 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -175,8 +175,8 @@ static bool qt_write_dibv5(QDataStream &s, QImage image) memset(buf, 0, bpl_bmp); for (int y=image.height()-1; y>=0; y--) { // write the image bits - QRgb *p = (QRgb *)image.scanLine(y); - QRgb *end = p + image.width(); + const QRgb *p = reinterpret_cast<const QRgb *>(image.constScanLine(y)); + const QRgb *end = p + image.width(); b = buf; while (p < end) { int alpha = qAlpha(*p); diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index 02696c87cd..bfcf96ebe7 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -77,22 +77,6 @@ static inline QDpi monitorDPI(HMONITOR hMonitor) #endif // !Q_OS_WINCE -static inline QSizeF deviceSizeMM(const QSize &pixels, const QDpi &dpi) -{ - const qreal inchToMM = 25.4; - const qreal h = qreal(pixels.width()) / qreal(dpi.first) * inchToMM; - const qreal v = qreal(pixels.height()) / qreal(dpi.second) * inchToMM; - return QSizeF(h, v); -} - -static inline QDpi deviceDPI(const QSize &pixels, const QSizeF &physicalSizeMM) -{ - const qreal inchToMM = 25.4; - const qreal h = qreal(pixels.width()) / (qreal(physicalSizeMM.width()) / inchToMM); - const qreal v = qreal(pixels.height()) / (qreal(physicalSizeMM.height()) / inchToMM); - return QDpi(h, v); -} - typedef QList<QWindowsScreenData> WindowsScreenDataList; static bool monitorData(HMONITOR hMonitor, QWindowsScreenData *data) diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index cc367ff801..5bbe923fe7 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -78,11 +78,6 @@ QT_BEGIN_NAMESPACE -static inline COLORREF qColorToCOLORREF(const QColor &color) -{ - return RGB(color.red(), color.green(), color.blue()); -} - static inline QColor COLORREFToQColor(COLORREF cr) { return QColor(GetRValue(cr), GetGValue(cr), GetBValue(cr)); @@ -99,30 +94,6 @@ static inline QTextStream& operator<<(QTextStream &str, const QColor &c) return str; } -static inline void paletteRoleToString(const QPalette &palette, - const QPalette::ColorRole role, - QTextStream &str) -{ - str << "Role: "; - str.setFieldWidth(2); - str.setPadChar(QLatin1Char('0')); - str << role; - str.setFieldWidth(0); - str << " Active: " << palette.color(QPalette::Active, role) - << " Disabled: " << palette.color(QPalette::Disabled, role) - << " Inactive: " << palette.color(QPalette::Inactive, role) - << '\n'; -} - -static inline QString paletteToString(const QPalette &palette) -{ - QString result; - QTextStream str(&result); - for (int r = 0; r < QPalette::NColorRoles; ++r) - paletteRoleToString(palette, static_cast<QPalette::ColorRole>(r), str); - return result; -} - static inline bool booleanSystemParametersInfo(UINT what, bool defaultValue) { BOOL result; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 7f45b4817a..2ff71d827b 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -183,7 +183,7 @@ static QPoint windowPlacementOffset(HWND hwnd, const QPoint &point) return QPoint(0, 0); const QWindowsScreenManager &screenManager = QWindowsContext::instance()->screenManager(); const QWindowsScreen *screen = screenManager.screens().size() == 1 - ? screenManager.screens().first() : screenManager.screenAtDp(point); + ? screenManager.screens().constFirst() : screenManager.screenAtDp(point); if (screen) return screen->availableGeometry().topLeft() - screen->geometry().topLeft(); #else @@ -248,13 +248,6 @@ static QWindow::Visibility windowVisibility_sys(HWND hwnd) return QWindow::Windowed; } -static inline QSize clientSize(HWND hwnd) -{ - RECT rect = { 0, 0, 0, 0 }; - GetClientRect(hwnd, &rect); // Always returns point 0,0, thus unusable for geometry. - return qSizeOfRect(rect); -} - static inline bool windowIsOpenGL(const QWindow *w) { switch (w->surfaceType()) { diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp index a0474b6710..9228ef8d62 100644 --- a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp +++ b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp @@ -169,12 +169,12 @@ void QWinRTInputContext::showInputPanel() ComPtr<IInputPane2> inputPane; HRESULT hr = getInputPane(&inputPane); if (FAILED(hr)) - return hr; + return S_OK; boolean success; hr = inputPane->TryShow(&success); if (FAILED(hr) || !success) qErrnoWarning(hr, "Failed to show input panel."); - return hr; + return S_OK; }); } @@ -184,12 +184,12 @@ void QWinRTInputContext::hideInputPanel() ComPtr<IInputPane2> inputPane; HRESULT hr = getInputPane(&inputPane); if (FAILED(hr)) - return hr; + return S_OK; boolean success; hr = inputPane->TryHide(&success); if (FAILED(hr) || !success) qErrnoWarning(hr, "Failed to hide input panel."); - return hr; + return S_OK; }); } diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 9cedd296e1..b9f6df1104 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -613,8 +613,8 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra initializeScreens(); initializeXRender(); - m_xi2Enabled = false; #if defined(XCB_USE_XINPUT2) + m_xi2Enabled = false; initializeXInput2(); #endif initializeXShape(); @@ -1133,8 +1133,16 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) handleClientMessageEvent((xcb_client_message_event_t *)event); break; case XCB_ENTER_NOTIFY: +#ifdef XCB_USE_XINPUT22 + if (isAtLeastXI22() && xi2MouseEvents()) + break; +#endif HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent); case XCB_LEAVE_NOTIFY: +#ifdef XCB_USE_XINPUT22 + if (isAtLeastXI22() && xi2MouseEvents()) + break; +#endif m_keyboard->updateXKBStateFromCore(((xcb_leave_notify_event_t *)event)->state); HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent); case XCB_FOCUS_IN: @@ -1922,6 +1930,7 @@ static const char * xcb_atomnames = { "Abs MT Position Y\0" "Abs MT Touch Major\0" "Abs MT Touch Minor\0" + "Abs MT Orientation\0" "Abs MT Pressure\0" "Abs MT Tracking ID\0" "Max Contacts\0" @@ -2216,13 +2225,15 @@ void QXcbConnection::initializeXKB() #endif } +#if defined(XCB_USE_XINPUT22) bool QXcbConnection::xi2MouseEvents() const { static bool mouseViaXI2 = !qEnvironmentVariableIsSet("QT_XCB_NO_XI2_MOUSE"); - // Don't use XInput2 when Xinerama extension is enabled, - // because it causes problems with multi-monitor setup. + // FIXME: Don't use XInput2 mouse events when Xinerama extension + // is enabled, because it causes problems with multi-monitor setup. return mouseViaXI2 && !has_xinerama_extension; } +#endif #if defined(XCB_USE_XINPUT2) static int xi2ValuatorOffset(unsigned char *maskPtr, int maskLen, int number) diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index a6a7b9e7ca..b799e46a36 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -261,6 +261,7 @@ namespace QXcbAtom { AbsMTPositionY, AbsMTTouchMajor, AbsMTTouchMinor, + AbsMTOrientation, AbsMTPressure, AbsMTTrackingID, MaxContacts, @@ -347,8 +348,10 @@ public: virtual void handleFocusInEvent(const xcb_focus_in_event_t *) {} virtual void handleFocusOutEvent(const xcb_focus_out_event_t *) {} virtual void handlePropertyNotifyEvent(const xcb_property_notify_event_t *) {} +#ifdef XCB_USE_XINPUT22 virtual void handleXIMouseEvent(xcb_ge_event_t *) {} - + virtual void handleXIEnterLeave(xcb_ge_event_t *) {} +#endif virtual QXcbWindow *toWindow() { return 0; } }; @@ -485,8 +488,8 @@ public: static bool xEmbedSystemTrayAvailable(); static bool xEmbedSystemTrayVisualHasAlphaChannel(); -#ifdef XCB_USE_XINPUT2 - void handleEnterEvent(const xcb_enter_notify_event_t *); +#ifdef XCB_USE_XINPUT21 + void handleEnterEvent(); #endif #ifdef XCB_USE_XINPUT22 @@ -500,7 +503,9 @@ public: QXcbGlIntegration *glIntegration() const { return m_glIntegration; } +#ifdef XCB_USE_XINPUT22 bool xi2MouseEvents() const; +#endif protected: bool event(QEvent *e) Q_DECL_OVERRIDE; @@ -534,9 +539,9 @@ private: void initializeScreens(); bool compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const; +#ifdef XCB_USE_XINPUT2 bool m_xi2Enabled; int m_xi2Minor; -#ifdef XCB_USE_XINPUT2 void initializeXInput2(); void finalizeXInput2(); void xi2SetupDevices(); diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index e055ad1424..969b6deed0 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -48,6 +48,7 @@ struct XInput2TouchDeviceData { XInput2TouchDeviceData() : xiDeviceInfo(0) , qtTouchDevice(0) + , providesTouchOrientation(false) { } XIDeviceInfo *xiDeviceInfo; @@ -59,6 +60,7 @@ struct XInput2TouchDeviceData { QPointF firstPressedPosition; // in screen coordinates where the first point was pressed QPointF firstPressedNormalPosition; // device coordinates (0 to 1, 0 to 1) where the first point was pressed QSizeF size; // device size in mm + bool providesTouchOrientation; }; void QXcbConnection::initializeXInput2() @@ -293,6 +295,11 @@ void QXcbConnection::xi2Select(xcb_window_t window) bitMask |= XI_ButtonPressMask; bitMask |= XI_ButtonReleaseMask; bitMask |= XI_MotionMask; + + // There is a check for enter/leave events in plain xcb enter/leave event handler + bitMask |= XI_EnterMask; + bitMask |= XI_LeaveMask; + qCDebug(lcQpaXInput, "XInput 2.2: Selecting press/release/motion events in addition to touch"); } XIEventMask mask; @@ -307,9 +314,12 @@ void QXcbConnection::xi2Select(xcb_window_t window) if (result != Success) qCDebug(lcQpaXInput, "XInput 2.2: failed to select pointer/touch events, window %x, result %d", window, result); } -#endif // XCB_USE_XINPUT22 const bool pointerSelected = isAtLeastXI22() && xi2MouseEvents(); +#else + const bool pointerSelected = false; +#endif // XCB_USE_XINPUT22 + QSet<int> tabletDevices; #ifndef QT_NO_TABLETEVENT if (!m_tabletData.isEmpty()) { @@ -413,6 +423,8 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id) caps |= QTouchDevice::Position | QTouchDevice::NormalizedPosition; else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor)) caps |= QTouchDevice::Area; + else if (vci->label == atom(QXcbAtom::AbsMTOrientation)) + dev->providesTouchOrientation = true; else if (vci->label == atom(QXcbAtom::AbsMTPressure) || vci->label == atom(QXcbAtom::AbsPressure)) caps |= QTouchDevice::Pressure; else if (vci->label == atom(QXcbAtom::RelX)) { @@ -474,6 +486,7 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event); int sourceDeviceId = xiEvent->deviceid; // may be the master id xXIDeviceEvent *xiDeviceEvent = 0; + xXIEnterEvent *xiEnterEvent = 0; QXcbWindowEventListener *eventListener = 0; switch (xiEvent->evtype) { @@ -488,14 +501,16 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) { xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event); eventListener = windowEventListenerFromId(xiDeviceEvent->event); - if (eventListener) { - long result = 0; - if (eventListener->handleGenericEvent(reinterpret_cast<xcb_generic_event_t *>(event), &result)) - return; - } sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id instead of the master break; } + case XI_Enter: + case XI_Leave: { + xiEnterEvent = reinterpret_cast<xXIEnterEvent *>(event); + eventListener = windowEventListenerFromId(xiEnterEvent->event); + sourceDeviceId = xiEnterEvent->sourceid; // use the actual device id instead of the master + break; + } case XI_HierarchyChanged: xi2HandleHierachyEvent(xiEvent); return; @@ -506,11 +521,19 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) break; } + if (eventListener) { + long result = 0; + if (eventListener->handleGenericEvent(reinterpret_cast<xcb_generic_event_t *>(event), &result)) + return; + } + #ifndef QT_NO_TABLETEVENT - for (int i = 0; i < m_tabletData.count(); ++i) { - if (m_tabletData.at(i).deviceId == sourceDeviceId) { - if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i], eventListener)) - return; + if (!xiEnterEvent) { + for (int i = 0; i < m_tabletData.count(); ++i) { + if (m_tabletData.at(i).deviceId == sourceDeviceId) { + if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i], eventListener)) + return; + } } } #endif // QT_NO_TABLETEVENT @@ -543,6 +566,13 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) xi2ProcessTouch(xiDeviceEvent, platformWindow); break; } + } else if (xiEnterEvent && xi2MouseEvents() && eventListener) { + switch (xiEnterEvent->evtype) { + case XI_Enter: + case XI_Leave: + eventListener->handleXIEnterLeave(event); + break; + } } #endif // XCB_USE_XINPUT22 } @@ -574,7 +604,9 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo QXcbScreen* screen = platformWindow->xcbScreen(); qreal x = fixed1616ToReal(xiDeviceEvent->root_x); qreal y = fixed1616ToReal(xiDeviceEvent->root_y); - qreal nx = -1.0, ny = -1.0, d = 0.0; + qreal nx = -1.0, ny = -1.0; + qreal w = 0.0, h = 0.0; + bool majorAxisIsY = touchPoint.area.height() > touchPoint.area.width(); for (int i = 0; i < dev->xiDeviceInfo->num_classes; ++i) { XIAnyClassInfo *classinfo = dev->xiDeviceInfo->classes[i]; if (classinfo->type == XIValuatorClass) { @@ -599,7 +631,24 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo } else if (vci->label == atom(QXcbAtom::AbsMTPositionY)) { ny = valuatorNormalized(value, vci); } else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor)) { - d = valuatorNormalized(value, vci) * screen->geometry().width(); + const qreal sw = screen->geometry().width(); + const qreal sh = screen->geometry().height(); + w = valuatorNormalized(value, vci) * std::sqrt(sw * sw + sh * sh); + } else if (vci->label == atom(QXcbAtom::AbsMTTouchMinor)) { + const qreal sw = screen->geometry().width(); + const qreal sh = screen->geometry().height(); + h = valuatorNormalized(value, vci) * std::sqrt(sw * sw + sh * sh); + } else if (vci->label == atom(QXcbAtom::AbsMTOrientation)) { + // Find the closest axis. + // 0 corresponds to the Y axis, vci->max to the X axis. + // Flipping over the Y axis and rotating by 180 degrees + // don't change the result, so normalize value to range + // [0, vci->max] first. + value = qAbs(value); + while (value > vci->max) + value -= 2 * vci->max; + value = qAbs(value); + majorAxisIsY = value < vci->max - value; } else if (vci->label == atom(QXcbAtom::AbsMTPressure) || vci->label == atom(QXcbAtom::AbsPressure)) { touchPoint.pressure = valuatorNormalized(value, vci); @@ -616,8 +665,18 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo ny = y / screen->geometry().height(); } if (xiDeviceEvent->evtype != XI_TouchEnd) { - if (d == 0.0) - d = touchPoint.area.width(); + if (!dev->providesTouchOrientation) { + if (w == 0.0) + w = touchPoint.area.width(); + h = w; + } else { + if (w == 0.0) + w = qMax(touchPoint.area.width(), touchPoint.area.height()); + if (h == 0.0) + h = qMin(touchPoint.area.width(), touchPoint.area.height()); + if (majorAxisIsY) + qSwap(w, h); + } } switch (xiDeviceEvent->evtype) { @@ -681,7 +740,7 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo } dev->pointPressedPosition.remove(touchPoint.id); } - touchPoint.area = QRectF(x - d/2, y - d/2, d, d); + touchPoint.area = QRectF(x - w/2, y - h/2, w, h); touchPoint.normalPosition = QPointF(nx, ny); if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled())) @@ -718,6 +777,8 @@ bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab) XISetMask(mask, XI_ButtonPress); XISetMask(mask, XI_ButtonRelease); XISetMask(mask, XI_Motion); + XISetMask(mask, XI_Enter); + XISetMask(mask, XI_Leave); XISetMask(mask, XI_TouchBegin); XISetMask(mask, XI_TouchUpdate); XISetMask(mask, XI_TouchEnd); @@ -827,9 +888,9 @@ void QXcbConnection::updateScrollingDevice(ScrollingDevice &scrollingDevice, int #endif } -void QXcbConnection::handleEnterEvent(const xcb_enter_notify_event_t *) -{ #ifdef XCB_USE_XINPUT21 +void QXcbConnection::handleEnterEvent() +{ QHash<int, ScrollingDevice>::iterator it = m_scrollingDevices.begin(); const QHash<int, ScrollingDevice>::iterator end = m_scrollingDevices.end(); while (it != end) { @@ -845,8 +906,8 @@ void QXcbConnection::handleEnterEvent(const xcb_enter_notify_event_t *) XIFreeDeviceInfo(xiDeviceInfo); ++it; } -#endif } +#endif void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice) { diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 19e8b1de7d..94e17a2983 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -174,9 +174,11 @@ QXcbIntegration::QXcbIntegration(const QStringList ¶meters, int &argc, char if (canNotGrabEnv) m_canGrab = false; + const int numParameters = parameters.size(); + m_connections.reserve(1 + numParameters / 2); m_connections << new QXcbConnection(m_nativeInterface.data(), m_canGrab, m_defaultVisualId, displayName); - for (int i = 0; i < parameters.size() - 1; i += 2) { + for (int i = 0; i < numParameters - 1; i += 2) { qCDebug(lcQpaScreen) << "connecting to additional display: " << parameters.at(i) << parameters.at(i+1); QString display = parameters.at(i) + QLatin1Char(':') + parameters.at(i+1); m_connections << new QXcbConnection(m_nativeInterface.data(), m_canGrab, m_defaultVisualId, display.toLatin1().constData()); diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 2e088d3ca5..631dd17908 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -797,9 +797,9 @@ void QXcbKeyboard::updateXKBStateFromCore(quint16 state) } } +#ifdef XCB_USE_XINPUT22 void QXcbKeyboard::updateXKBStateFromXI(void *modInfo, void *groupInfo) { -#ifdef XCB_USE_XINPUT22 if (m_config && !connection()->hasXKB()) { xXIModifierInfo *mods = static_cast<xXIModifierInfo *>(modInfo); xXIGroupInfo *group = static_cast<xXIGroupInfo *>(groupInfo); @@ -815,12 +815,8 @@ void QXcbKeyboard::updateXKBStateFromXI(void *modInfo, void *groupInfo) //qWarning("TODO: Support KeyboardLayoutChange on QPA (QTBUG-27681)"); } } -#else - Q_UNUSED(modInfo); - Q_UNUSED(groupInfo); - Q_ASSERT(false); // this can't be -#endif } +#endif quint32 QXcbKeyboard::xkbModMask(quint16 state) { diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h index d2e37d624c..457a27affb 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.h +++ b/src/plugins/platforms/xcb/qxcbkeyboard.h @@ -68,7 +68,9 @@ public: void updateXKBMods(); quint32 xkbModMask(quint16 state); void updateXKBStateFromCore(quint16 state); +#ifdef XCB_USE_XINPUT22 void updateXKBStateFromXI(void *modInfo, void *groupInfo); +#endif #ifndef QT_NO_XKB // when XKEYBOARD is present on the X server int coreDeviceId() const { return core_device_id; } diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index f97f570831..46b7b70f80 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -894,8 +894,13 @@ static bool focusInPeeker(QXcbConnection *connection, xcb_generic_event_t *event return true; } uint response_type = event->response_type & ~0x80; - if (response_type == XCB_FOCUS_IN) - return true; + if (response_type == XCB_FOCUS_IN) { + // Ignore focus events that are being sent only because the pointer is over + // our window, even if the input focus is in a different window. + xcb_focus_in_event_t *e = (xcb_focus_in_event_t *) event; + if (e->detail != XCB_NOTIFY_DETAIL_POINTER) + return true; + } /* We are also interested in XEMBED_FOCUS_IN events */ if (response_type == XCB_CLIENT_MESSAGE) { @@ -2157,6 +2162,85 @@ void QXcbWindow::handleButtonReleaseEvent(int event_x, int event_y, int root_x, handleMouseEvent(timestamp, local, global, modifiers); } +static bool ignoreLeaveEvent(quint8 mode, quint8 detail) +{ + return (mode == XCB_NOTIFY_MODE_GRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR) // Check for AwesomeWM + || detail == XCB_NOTIFY_DETAIL_VIRTUAL + || detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL; +} + +static bool ignoreEnterEvent(quint8 mode, quint8 detail) +{ + return ((mode == XCB_NOTIFY_MODE_UNGRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR) // Check for AwesomeWM + || (mode != XCB_NOTIFY_MODE_NORMAL && mode != XCB_NOTIFY_MODE_UNGRAB) + || detail == XCB_NOTIFY_DETAIL_VIRTUAL + || detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL); +} + +class EnterEventChecker +{ +public: + bool checkEvent(xcb_generic_event_t *event) + { + if (!event) + return false; + if ((event->response_type & ~0x80) != XCB_ENTER_NOTIFY) + return false; + + xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)event; + if (ignoreEnterEvent(enter->mode, enter->detail)) + return false; + + return true; + } +}; + +void QXcbWindow::handleEnterNotifyEvent(int event_x, int event_y, int root_x, int root_y, + quint8 mode, quint8 detail, xcb_timestamp_t timestamp) +{ + connection()->setTime(timestamp); +#ifdef XCB_USE_XINPUT21 + connection()->handleEnterEvent(); +#endif + + const QPoint global = QPoint(root_x, root_y); + + if (ignoreEnterEvent(mode, detail) + || (connection()->buttons() != Qt::NoButton + && QGuiApplicationPrivate::lastCursorPosition != global)) + return; + + const QPoint local(event_x, event_y); + QWindowSystemInterface::handleEnterEvent(window(), local, global); +} + +void QXcbWindow::handleLeaveNotifyEvent(int root_x, int root_y, + quint8 mode, quint8 detail, xcb_timestamp_t timestamp) +{ + connection()->setTime(timestamp); + + const QPoint global(root_x, root_y); + + if (ignoreLeaveEvent(mode, detail) + || (connection()->buttons() != Qt::NoButton + && QGuiApplicationPrivate::lastCursorPosition != global)) + return; + + EnterEventChecker checker; + xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)connection()->checkEvent(checker); + QXcbWindow *enterWindow = enter ? connection()->platformWindowFromId(enter->event) : 0; + + if (enterWindow) { + QPoint local(enter->event_x, enter->event_y); + QPoint global = QPoint(root_x, root_y); + QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global); + } else { + QWindowSystemInterface::handleLeaveEvent(window()); + } + + free(enter); +} + void QXcbWindow::handleMotionNotifyEvent(int event_x, int event_y, int root_x, int root_y, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp) { @@ -2191,12 +2275,10 @@ static inline int fixed1616ToInt(FP1616 val) { return int((qreal(val >> 16)) + (val & 0xFFFF) / (qreal)0xFFFF); } -#endif // With XI 2.2+ press/release/motion comes here instead of the above handlers. void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event) { -#ifdef XCB_USE_XINPUT22 QXcbConnection *conn = connection(); xXIDeviceEvent *ev = reinterpret_cast<xXIDeviceEvent *>(event); const Qt::KeyboardModifiers modifiers = conn->keyboard()->translateModifiers(ev->mods.effective_mods); @@ -2234,12 +2316,41 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event) qWarning() << "Unrecognized XI2 mouse event" << ev->evtype; break; } -#else - Q_UNUSED(event); - Q_ASSERT(false); // this can't be -#endif } +// With XI 2.2+ enter/leave comes here and are blocked in plain xcb events +void QXcbWindow::handleXIEnterLeave(xcb_ge_event_t *event) +{ + xXIEnterEvent *ev = reinterpret_cast<xXIEnterEvent *>(event); + + // Compare the window with current mouse grabber to prevent deliver events to any other windows. + // If leave event occurs and the window is under mouse - allow to deliver the leave event. + QXcbWindow *mouseGrabber = connection()->mouseGrabber(); + if (mouseGrabber && mouseGrabber != this + && (ev->evtype != XI_Leave || QGuiApplicationPrivate::currentMouseWindow != window())) { + return; + } + + const int root_x = fixed1616ToInt(ev->root_x); + const int root_y = fixed1616ToInt(ev->root_y); + + switch (ev->evtype) { + case XI_Enter: { + const int event_x = fixed1616ToInt(ev->event_x); + const int event_y = fixed1616ToInt(ev->event_y); + qCDebug(lcQpaXInput, "XI2 mouse enter %d,%d, mode %d, detail %d, time %d", event_x, event_y, ev->mode, ev->detail, ev->time); + handleEnterNotifyEvent(event_x, event_y, root_x, root_y, ev->mode, ev->detail, ev->time); + break; + } + case XI_Leave: + qCDebug(lcQpaXInput, "XI2 mouse leave, mode %d, detail %d, time %d", ev->mode, ev->detail, ev->time); + connection()->keyboard()->updateXKBStateFromXI(&ev->mods, &ev->group); + handleLeaveNotifyEvent(root_x, root_y, ev->mode, ev->detail, ev->time); + break; + } +} +#endif + QXcbWindow *QXcbWindow::toWindow() { return this; } void QXcbWindow::handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global, Qt::KeyboardModifiers modifiers) @@ -2248,74 +2359,14 @@ void QXcbWindow::handleMouseEvent(xcb_timestamp_t time, const QPoint &local, con QWindowSystemInterface::handleMouseEvent(window(), time, local, global, connection()->buttons(), modifiers); } -static bool ignoreLeaveEvent(const xcb_leave_notify_event_t *event) -{ - return event->detail == XCB_NOTIFY_DETAIL_VIRTUAL - || event->detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL - || event->mode == XCB_NOTIFY_MODE_GRAB; -} - -static bool ignoreEnterEvent(const xcb_enter_notify_event_t *event) -{ - return (event->mode != XCB_NOTIFY_MODE_NORMAL - || event->detail == XCB_NOTIFY_DETAIL_VIRTUAL - || event->detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL); -} - -class EnterEventChecker -{ -public: - bool checkEvent(xcb_generic_event_t *event) - { - if (!event) - return false; - if ((event->response_type & ~0x80) != XCB_ENTER_NOTIFY) - return false; - - xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)event; - if (ignoreEnterEvent(enter)) - return false; - - return true; - } -}; - void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event) { - connection()->setTime(event->time); -#ifdef XCB_USE_XINPUT2 - connection()->handleEnterEvent(event); -#endif - - if (ignoreEnterEvent(event)) - return; - - const QPoint local(event->event_x, event->event_y); - QPoint global = QPoint(event->root_x, event->root_y); - QWindowSystemInterface::handleEnterEvent(window(), local, global); + handleEnterNotifyEvent(event->event_x, event->event_y, event->root_x, event->root_y, event->mode, event->detail, event->time); } void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event) { - connection()->setTime(event->time); - - if (ignoreLeaveEvent(event)) - return; - - EnterEventChecker checker; - xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)connection()->checkEvent(checker); - QXcbWindow *enterWindow = enter ? connection()->platformWindowFromId(enter->event) : 0; - - if (enterWindow) { - QPoint local(enter->event_x, enter->event_y); - QPoint global = QPoint(event->root_x, event->root_y); - - QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global); - } else { - QWindowSystemInterface::handleLeaveEvent(window()); - } - - free(enter); + handleLeaveNotifyEvent(event->root_x, event->root_y, event->mode, event->detail, event->time); } void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) @@ -2369,14 +2420,22 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev } } -void QXcbWindow::handleFocusInEvent(const xcb_focus_in_event_t *) +void QXcbWindow::handleFocusInEvent(const xcb_focus_in_event_t *event) { + // Ignore focus events that are being sent only because the pointer is over + // our window, even if the input focus is in a different window. + if (event->detail == XCB_NOTIFY_DETAIL_POINTER) + return; doFocusIn(); } -void QXcbWindow::handleFocusOutEvent(const xcb_focus_out_event_t *) +void QXcbWindow::handleFocusOutEvent(const xcb_focus_out_event_t *event) { + // Ignore focus events that are being sent only because the pointer is over + // our window, even if the input focus is in a different window. + if (event->detail == XCB_NOTIFY_DETAIL_POINTER) + return; doFocusOut(); } @@ -2419,7 +2478,7 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab) if (!grab && connection()->mouseGrabber() == this) connection()->setMouseGrabber(Q_NULLPTR); #ifdef XCB_USE_XINPUT22 - if (connection()->xi2MouseEvents()) { + if (connection()->isAtLeastXI22() && connection()->xi2MouseEvents()) { bool result = connection()->xi2SetMouseGrabEnabled(m_window, grab); if (grab && result) connection()->setMouseGrabber(this); diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index d2c02fe3df..69790f29ae 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -132,7 +132,10 @@ public: void handleFocusInEvent(const xcb_focus_in_event_t *event) Q_DECL_OVERRIDE; void handleFocusOutEvent(const xcb_focus_out_event_t *event) Q_DECL_OVERRIDE; void handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) Q_DECL_OVERRIDE; +#ifdef XCB_USE_XINPUT22 void handleXIMouseEvent(xcb_ge_event_t *) Q_DECL_OVERRIDE; + void handleXIEnterLeave(xcb_ge_event_t *) Q_DECL_OVERRIDE; +#endif QXcbWindow *toWindow() Q_DECL_OVERRIDE; @@ -212,6 +215,12 @@ protected: void handleMotionNotifyEvent(int event_x, int event_y, int root_x, int root_y, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp); + void handleEnterNotifyEvent(int event_x, int event_y, int root_x, int root_y, + quint8 mode, quint8 detail, xcb_timestamp_t timestamp); + + void handleLeaveNotifyEvent(int root_x, int root_y, + quint8 mode, quint8 detail, xcb_timestamp_t timestamp); + xcb_window_t m_window; uint m_depth; |