diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/3rdparty/harfbuzz-ng/src/config.h | 1 | ||||
-rw-r--r-- | src/corelib/codecs/qutfcodec.cpp | 44 | ||||
-rw-r--r-- | src/corelib/tools/qhash.cpp | 2 | ||||
-rw-r--r-- | src/network/doc/src/ssl.qdoc | 2 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 62 |
5 files changed, 80 insertions, 31 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/config.h b/src/3rdparty/harfbuzz-ng/src/config.h index cb68ab0e5b..9abb5df7f1 100644 --- a/src/3rdparty/harfbuzz-ng/src/config.h +++ b/src/3rdparty/harfbuzz-ng/src/config.h @@ -4,7 +4,6 @@ #define HAVE_OT #define HAVE_ATEXIT -#define HB_NO_MT #define HB_NO_UNICODE_FUNCS #define HB_DISABLE_DEPRECATED diff --git a/src/corelib/codecs/qutfcodec.cpp b/src/corelib/codecs/qutfcodec.cpp index 072cda63aa..c5f580e13d 100644 --- a/src/corelib/codecs/qutfcodec.cpp +++ b/src/corelib/codecs/qutfcodec.cpp @@ -237,7 +237,20 @@ QByteArray QUtf8::convertFromUnicode(const QChar *uc, int len, QTextCodec::Conve QString QUtf8::convertToUnicode(const char *chars, int len) { - QString result(len + 1, Qt::Uninitialized); // worst case + // UTF-8 to UTF-16 always needs the exact same number of words or less: + // UTF-8 UTF-16 + // 1 byte 1 word + // 2 bytes 1 word + // 3 bytes 1 word + // 4 bytes 2 words (one surrogate pair) + // That is, we'll use the full buffer if the input is US-ASCII (1-byte UTF-8), + // half the buffer for U+0080-U+07FF text (e.g., Greek, Cyrillic, Arabic) or + // non-BMP text, and one third of the buffer for U+0800-U+FFFF text (e.g, CJK). + // + // The table holds for invalid sequences too: we'll insert one replacement char + // per invalid byte. + QString result(len, Qt::Uninitialized); + ushort *dst = reinterpret_cast<ushort *>(const_cast<QChar *>(result.constData())); const uchar *src = reinterpret_cast<const uchar *>(chars); const uchar *end = src + len; @@ -282,7 +295,18 @@ QString QUtf8::convertToUnicode(const char *chars, int len, QTextCodec::Converte int res; uchar ch = 0; - QString result(need + len + 1, Qt::Uninitialized); // worst case + // See above for buffer requirements for stateless decoding. However, that + // fails if the state is not empty. The following situations can add to the + // requirements: + // state contains chars starts with requirement + // 1 of 2 bytes valid continuation 0 + // 2 of 3 bytes same 0 + // 3 bytes of 4 same +1 (need to insert surrogate pair) + // 1 of 2 bytes invalid continuation +1 (need to insert replacement and restart) + // 2 of 3 bytes same +1 (same) + // 3 of 4 bytes same +1 (same) + QString result(need + len + 1, Qt::Uninitialized); + ushort *dst = reinterpret_cast<ushort *>(const_cast<QChar *>(result.constData())); const uchar *src = reinterpret_cast<const uchar *>(chars); const uchar *end = src + len; @@ -305,15 +329,17 @@ QString QUtf8::convertToUnicode(const char *chars, int len, QTextCodec::Converte const uchar *begin = &remainingCharsData[1]; res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(remainingCharsData[0], dst, begin, static_cast<const uchar *>(remainingCharsData) + remainingCharsCount + newCharsToCopy); - if (res == QUtf8BaseTraits::EndOfString) { + if (res == QUtf8BaseTraits::Error || (res == QUtf8BaseTraits::EndOfString && len == 0)) { + // special case for len == 0: + // if we were supplied an empty string, terminate the previous, unfinished sequence with error + ++invalid; + *dst++ = replacement; + } else if (res == QUtf8BaseTraits::EndOfString) { // if we got EndOfString again, then there were too few bytes in src; // copy to our state and return state->remainingChars = remainingCharsCount + newCharsToCopy; memcpy(&state->state_data[0], remainingCharsData, state->remainingChars); return QString(); - } else if (res == QUtf8BaseTraits::Error) { - ++invalid; - *dst++ = replacement; } else if (!headerdone && res >= 0) { // eat the UTF-8 BOM headerdone = true; @@ -322,8 +348,10 @@ QString QUtf8::convertToUnicode(const char *chars, int len, QTextCodec::Converte } // adjust src now that we have maybe consumed a few chars - //Q_ASSERT(res > remainingCharsCount) - src += res - remainingCharsCount; + if (res >= 0) { + Q_ASSERT(res > remainingCharsCount); + src += res - remainingCharsCount; + } } } diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index a5d14a3535..ca645636e4 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -125,7 +125,7 @@ static uint crc32(const Char *ptr, size_t len, uint h) # else p += 4; for ( ; p <= e; p += 4) - h = _mm_crc32_u32(h, *reinterpret_cast<const uint *>(p)); + h = _mm_crc32_u32(h, *reinterpret_cast<const uint *>(p - 4)); p -= 4; len = e - p; # endif diff --git a/src/network/doc/src/ssl.qdoc b/src/network/doc/src/ssl.qdoc index e1bb1b9316..77fbec9943 100644 --- a/src/network/doc/src/ssl.qdoc +++ b/src/network/doc/src/ssl.qdoc @@ -57,7 +57,7 @@ system: \code - ./configure -openssl-linked OPENSSL_LIBS='-L/opt/ssl/lib -lssl -lcrypto' + OPENSSL_LIBS='-L/opt/ssl/lib -lssl -lcrypto' ./configure -openssl-linked \endcode To disable SSL support in a Qt build, configure Qt with the \c{-no-openssl} diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index efa1691780..eb7b220c43 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -148,15 +148,17 @@ void QXcbConnection::initializeXInput2() } case XIButtonClass: { XIButtonClassInfo *bci = reinterpret_cast<XIButtonClassInfo *>(devices[i].classes[c]); - for (int i=0; i < bci->num_buttons; ++i) { - const int buttonAtom = qatom(bci->labels[i]); - if (buttonAtom == QXcbAtom::ButtonWheelUp - || buttonAtom == QXcbAtom::ButtonWheelDown) { + if (bci->num_buttons >= 5) { + Atom label4 = bci->labels[3]; + Atom label5 = bci->labels[4]; + if ((!label4 || qatom(label4) == QXcbAtom::ButtonWheelUp) && (!label5 || qatom(label5) == QXcbAtom::ButtonWheelDown)) scrollingDevice.legacyOrientations |= Qt::Vertical; - } else if (buttonAtom == QXcbAtom::ButtonHorizWheelLeft - || buttonAtom == QXcbAtom::ButtonHorizWheelRight) { + } + if (bci->num_buttons >= 7) { + Atom label6 = bci->labels[5]; + Atom label7 = bci->labels[6]; + if ((!label6 || qatom(label6) == QXcbAtom::ButtonHorizWheelLeft) && (!label7 || qatom(label7) == QXcbAtom::ButtonHorizWheelRight)) scrollingDevice.legacyOrientations |= Qt::Horizontal; - } } break; } @@ -246,6 +248,7 @@ void QXcbConnection::xi2Select(xcb_window_t window) } #endif // XCB_USE_XINPUT22 + QSet<int> tabletDevices; #ifndef QT_NO_TABLETEVENT // For each tablet, select some additional event types. // Press, motion, etc. events must never be selected for _all_ devices @@ -253,15 +256,19 @@ void QXcbConnection::xi2Select(xcb_window_t window) // similar handlers useless and we have no intention to infect // all the pure xcb code with Xlib-based XI2. if (!m_tabletData.isEmpty()) { + unsigned int tabletBitMask = bitMask; + unsigned char *xiTabletBitMask = reinterpret_cast<unsigned char *>(&tabletBitMask); QVector<XIEventMask> xiEventMask(m_tabletData.count()); - bitMask |= XI_ButtonPressMask; - bitMask |= XI_ButtonReleaseMask; - bitMask |= XI_MotionMask; - bitMask |= XI_PropertyEventMask; + tabletBitMask |= XI_ButtonPressMask; + tabletBitMask |= XI_ButtonReleaseMask; + tabletBitMask |= XI_MotionMask; + tabletBitMask |= XI_PropertyEventMask; for (int i = 0; i < m_tabletData.count(); ++i) { - xiEventMask[i].deviceid = m_tabletData.at(i).deviceId; - xiEventMask[i].mask_len = sizeof(bitMask); - xiEventMask[i].mask = xiBitMask; + int deviceId = m_tabletData.at(i).deviceId; + tabletDevices.insert(deviceId); + xiEventMask[i].deviceid = deviceId; + xiEventMask[i].mask_len = sizeof(tabletBitMask); + xiEventMask[i].mask = xiTabletBitMask; } XISelectEvents(xDisplay, window, xiEventMask.data(), m_tabletData.count()); } @@ -271,17 +278,30 @@ void QXcbConnection::xi2Select(xcb_window_t window) // Enable each scroll device if (!m_scrollingDevices.isEmpty()) { QVector<XIEventMask> xiEventMask(m_scrollingDevices.size()); - bitMask = XI_MotionMask; + unsigned int scrollBitMask = 0; + unsigned char *xiScrollBitMask = reinterpret_cast<unsigned char *>(&scrollBitMask); + scrollBitMask = XI_MotionMask; + scrollBitMask |= XI_ButtonReleaseMask; + bitMask |= XI_MotionMask; bitMask |= XI_ButtonReleaseMask; int i=0; Q_FOREACH (const ScrollingDevice& scrollingDevice, m_scrollingDevices) { + if (tabletDevices.contains(scrollingDevice.deviceId)) + continue; // All necessary events are already captured. xiEventMask[i].deviceid = scrollingDevice.deviceId; - xiEventMask[i].mask_len = sizeof(bitMask); - xiEventMask[i].mask = xiBitMask; + if (m_touchDevices.contains(scrollingDevice.deviceId)) { + xiEventMask[i].mask_len = sizeof(bitMask); + xiEventMask[i].mask = xiBitMask; + } else { + xiEventMask[i].mask_len = sizeof(scrollBitMask); + xiEventMask[i].mask = xiScrollBitMask; + } i++; } - XISelectEvents(xDisplay, window, xiEventMask.data(), m_scrollingDevices.size()); + XISelectEvents(xDisplay, window, xiEventMask.data(), i); } +#else + Q_UNUSED(xiBitMask); #endif } @@ -655,13 +675,15 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData) if (reinterpret_cast<xXIDeviceEvent *>(event)->detail == 1) { // ignore the physical buttons on the stylus tabletData->down = true; xi2ReportTabletEvent(*tabletData, xiEvent); - } + } else + handled = false; break; case XI_ButtonRelease: // stylus up if (reinterpret_cast<xXIDeviceEvent *>(event)->detail == 1) { tabletData->down = false; xi2ReportTabletEvent(*tabletData, xiEvent); - } + } else + handled = false; break; case XI_Motion: // Report TabletMove only when the stylus is touching the tablet. |