From 86ca2acfe9e165d09c14b91c9a1c9382ff50c1ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=93=81=E9=BE=99?= Date: Fri, 5 May 2023 17:25:02 +0800 Subject: [PATCH] fix-build-error --- debian/changelog | 2 +- src/concurrent/qtconcurrentthreadengine.cpp | 33 +++ src/concurrent/qtconcurrentthreadengine.h | 23 ++ src/gui/image/qimagereader.cpp | 6 +- src/gui/image/qimagewriter.cpp | 6 +- src/gui/kernel/qguiapplication.cpp | 12 +- src/network/ssl/qsslcontext_openssl.cpp | 2 +- src/network/ssl/qsslsocket_openssl.cpp | 4 +- src/network/ssl/qsslsocket_openssl_p.h | 8 +- .../ssl/qsslsocket_openssl_symbols.cpp | 2 +- .../ssl/qsslsocket_openssl_symbols_p.h | 2 +- .../input/xkbcommon/qxkbcommon.cpp | 12 +- .../input/xkbcommon/qxkbcommon_p.h | 4 +- .../platforms/xcb/qxcbconnection_xi2.cpp | 4 - src/plugins/platforms/xcb/qxcbwindow.cpp | 139 +++--------- src/plugins/platforms/xcb/qxcbwindow.h | 19 +- src/plugins/sqldrivers/odbc/qsql_odbc.cpp | 206 ++++++++++-------- src/widgets/widgets/qmenu.cpp | 25 +++ src/widgets/widgets/qmenu_p.h | 1 + .../kernel/qapplication/tst_qapplication.cpp | 4 +- 20 files changed, 268 insertions(+), 246 deletions(-) diff --git a/debian/changelog b/debian/changelog index 4aed20ef..144c0222 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -qtbase-opensource-src (5.15.8+dfsg-ok1.1test2) yangtze; urgency=medium +qtbase-opensource-src (5.15.8+dfsg-ok1.1test3) yangtze; urgency=medium * rebuild diff --git a/src/concurrent/qtconcurrentthreadengine.cpp b/src/concurrent/qtconcurrentthreadengine.cpp index ea6ce3ac..7f91a2ba 100644 --- a/src/concurrent/qtconcurrentthreadengine.cpp +++ b/src/concurrent/qtconcurrentthreadengine.cpp @@ -176,6 +176,39 @@ void ThreadEngineBase::startSingleThreaded() finish(); } +void ThreadEngineBase::startBlocking() +{ + start(); + barrier.acquire(); + startThreads(); + + bool throttled = false; +#ifndef QT_NO_EXCEPTIONS + try { +#endif + while (threadFunction() == ThrottleThread) { + if (threadThrottleExit()) { + throttled = true; + break; + } + } +#ifndef QT_NO_EXCEPTIONS + } catch (QException &e) { + handleException(e); + } catch (...) { + handleException(QUnhandledException()); + } +#endif + + if (throttled == false) { + barrier.release(); + } + + barrier.wait(); + finish(); + exceptionStore.throwPossibleException(); +} + void ThreadEngineBase::startThread() { startThreadInternal(); diff --git a/src/concurrent/qtconcurrentthreadengine.h b/src/concurrent/qtconcurrentthreadengine.h index 7c30cebd..a4c8548c 100644 --- a/src/concurrent/qtconcurrentthreadengine.h +++ b/src/concurrent/qtconcurrentthreadengine.h @@ -91,6 +91,7 @@ public: ThreadEngineBase(); virtual ~ThreadEngineBase(); void startSingleThreaded(); + void startBlocking(); void startThread(); bool isCanceled(); void waitForResume(); @@ -143,6 +144,15 @@ public: return result(); } + // Runs the user algorithm using multiple threads. + // This function blocks until the algorithm is finished, + // and then returns the result. + T *startBlocking() + { + ThreadEngineBase::startBlocking(); + return result(); + } + // Runs the user algorithm using multiple threads. // Does not block, returns a future. QFuture startAsynchronously() @@ -223,6 +233,13 @@ class ThreadEngineStarter : public ThreadEngineStarterBase public: ThreadEngineStarter(TypedThreadEngine *eng) : Base(eng) { } + + T startBlocking() + { + T t = *this->threadEngine->startBlocking(); + delete this->threadEngine; + return t; + } }; // Full template specialization where T is void. @@ -232,6 +249,12 @@ class ThreadEngineStarter : public ThreadEngineStarterBase public: ThreadEngineStarter(ThreadEngine *_threadEngine) : ThreadEngineStarterBase(_threadEngine) {} + + void startBlocking() + { + this->threadEngine->startBlocking(); + delete this->threadEngine; + } }; //! [qtconcurrentthreadengine-1] diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index 5cb7e132..1274622d 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -515,9 +515,9 @@ QImageReaderPrivate::QImageReaderPrivate(QImageReader *qq) */ QImageReaderPrivate::~QImageReaderPrivate() { + delete handler; if (deleteDevice) delete device; - delete handler; } /*! @@ -774,12 +774,12 @@ bool QImageReader::decideFormatFromContent() const */ void QImageReader::setDevice(QIODevice *device) { + delete d->handler; + d->handler = nullptr; if (d->device && d->deleteDevice) delete d->device; d->device = device; d->deleteDevice = false; - delete d->handler; - d->handler = nullptr; d->text.clear(); } diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp index 33f5e491..a679f257 100644 --- a/src/gui/image/qimagewriter.cpp +++ b/src/gui/image/qimagewriter.cpp @@ -349,9 +349,9 @@ QImageWriter::QImageWriter(const QString &fileName, const QByteArray &format) */ QImageWriter::~QImageWriter() { + delete d->handler; if (d->deleteDevice) delete d->device; - delete d->handler; delete d; } @@ -396,13 +396,13 @@ QByteArray QImageWriter::format() const */ void QImageWriter::setDevice(QIODevice *device) { + delete d->handler; + d->handler = nullptr; if (d->device && d->deleteDevice) delete d->device; d->device = device; d->deleteDevice = false; - delete d->handler; - d->handler = nullptr; } /*! diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index aee9b8dc..8282bd34 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1412,14 +1412,7 @@ void QGuiApplicationPrivate::createPlatformIntegration() if (sessionType == QByteArrayLiteral("x11") && !platformName.contains(QByteArrayLiteral("xcb"))) { platformName = QByteArrayLiteral("xcb"); } else if (sessionType == QByteArrayLiteral("wayland") && !platformName.contains(QByteArrayLiteral("wayland"))) { - QByteArray currentDesktop = qgetenv("XDG_CURRENT_DESKTOP").toLower(); - QByteArray sessionDesktop = qgetenv("XDG_SESSION_DESKTOP").toLower(); - if (currentDesktop.contains("gnome") || sessionDesktop.contains("gnome")) { - qInfo() << "Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome." - << "Use QT_QPA_PLATFORM=wayland to run on Wayland anyway."; - } else { - platformName = QByteArrayLiteral("wayland"); - } + platformName = QByteArrayLiteral("wayland"); } } #ifdef QT_QPA_DEFAULT_PLATFORM_NAME @@ -3064,8 +3057,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To QEvent::Type mouseEventType = QEvent::MouseMove; Qt::MouseButton button = Qt::NoButton; Qt::MouseButtons buttons = Qt::LeftButton; - if ((eventType == QEvent::TouchBegin && m_fakeMouseSourcePointId < 0) - || (touchPoints.count() == 1 && m_fakeMouseSourcePointId != touchPoints.first().id())) + if (eventType == QEvent::TouchBegin && m_fakeMouseSourcePointId < 0) m_fakeMouseSourcePointId = touchPoints.first().id(); for (const auto &touchPoint : touchPoints) { if (touchPoint.id() == m_fakeMouseSourcePointId) { diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp index d0a428c2..c992da9d 100644 --- a/src/network/ssl/qsslcontext_openssl.cpp +++ b/src/network/ssl/qsslcontext_openssl.cpp @@ -455,7 +455,7 @@ init_context: } // Enable bug workarounds. - long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions); + qssloptions options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions); q_SSL_CTX_set_options(sslContext->ctx, options); // Tell OpenSSL to release memory early diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 37fad2a6..8f6858c8 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -550,9 +550,9 @@ static void q_loadCiphersForConnection(SSL *connection, QList &ciphe // Defined in qsslsocket.cpp void q_setDefaultDtlsCiphers(const QList &ciphers); -long QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions) +qssloptions QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions) { - long options; + qssloptions options; if (protocol == QSsl::TlsV1SslV3) options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3; else if (protocol == QSsl::SecureProtocols) diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h index 4103de23..55475892 100644 --- a/src/network/ssl/qsslsocket_openssl_p.h +++ b/src/network/ssl/qsslsocket_openssl_p.h @@ -107,6 +107,12 @@ QT_BEGIN_NAMESPACE +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 +typedef uint64_t qssloptions; +#else +typedef unsigned long qssloptions; +#endif + struct QSslErrorEntry { int code; int depth; @@ -171,7 +177,7 @@ public: QVector ocspErrors; QByteArray ocspResponseDer; - Q_AUTOTEST_EXPORT static long setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions); + Q_AUTOTEST_EXPORT static qssloptions setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions); static QSslCipher QSslCipher_from_SSL_CIPHER(const SSL_CIPHER *cipher); static QList STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509); static QList verify(const QList &certificateChain, const QString &hostName); diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index 68a766c0..459ccd0b 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -157,7 +157,7 @@ DEFINEFUNC2(void, OPENSSL_sk_push, OPENSSL_STACK *a, a, void *b, b, return, DUMM DEFINEFUNC(void, OPENSSL_sk_free, OPENSSL_STACK *a, a, return, DUMMYARG) DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return nullptr, return) DEFINEFUNC(int, SSL_session_reused, SSL *a, a, return 0, return) -DEFINEFUNC2(unsigned long, SSL_CTX_set_options, SSL_CTX *ctx, ctx, unsigned long op, op, return 0, return) +DEFINEFUNC2(qssloptions, SSL_CTX_set_options, SSL_CTX *ctx, ctx, qssloptions op, op, return 0, return) DEFINEFUNC(int, SSL_CTX_get_security_level, const SSL_CTX *ctx, ctx, return -1, return) DEFINEFUNC2(void, SSL_CTX_set_security_level, SSL_CTX *ctx, ctx, int level, level, return, return) #ifdef TLS1_3_VERSION diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index 71961775..27aeffa1 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -245,7 +245,7 @@ Q_AUTOTEST_EXPORT void q_OPENSSL_sk_push(OPENSSL_STACK *st, void *data); Q_AUTOTEST_EXPORT void q_OPENSSL_sk_free(OPENSSL_STACK *a); Q_AUTOTEST_EXPORT void * q_OPENSSL_sk_value(OPENSSL_STACK *a, int b); int q_SSL_session_reused(SSL *a); -unsigned long q_SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op); +qssloptions q_SSL_CTX_set_options(SSL_CTX *ctx, qssloptions op); int q_OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings); size_t q_SSL_get_client_random(SSL *a, unsigned char *out, size_t outlen); size_t q_SSL_SESSION_get_master_key(const SSL_SESSION *session, unsigned char *out, size_t outlen); diff --git a/src/platformsupport/input/xkbcommon/qxkbcommon.cpp b/src/platformsupport/input/xkbcommon/qxkbcommon.cpp index b713c194..0c8545b8 100644 --- a/src/platformsupport/input/xkbcommon/qxkbcommon.cpp +++ b/src/platformsupport/input/xkbcommon/qxkbcommon.cpp @@ -471,7 +471,7 @@ QVector QXkbCommon::toKeysym(QKeyEvent *event) } else if (event->modifiers() & Qt::KeypadModifier) { if (qtKey >= Qt::Key_0 && qtKey <= Qt::Key_9) keysyms.append(XKB_KEY_KP_0 + (qtKey - Qt::Key_0)); - } else if (isLatin(qtKey) && event->text().isUpper()) { + } else if (isLatin1(qtKey) && event->text().isUpper()) { keysyms.append(qtKey); } @@ -523,7 +523,7 @@ int QXkbCommon::keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers modifie // With standard shortcuts we should prefer a latin character, this is // for checks like "some qkeyevent == QKeySequence::Copy" to work even // when using for example 'russian' keyboard layout. - if (!QXkbCommon::isLatin(keysym)) { + if (!QXkbCommon::isLatin1(keysym)) { xkb_keysym_t latinKeysym = QXkbCommon::lookupLatinKeysym(state, code); if (latinKeysym != XKB_KEY_NoSymbol) keysym = latinKeysym; @@ -546,7 +546,7 @@ static int keysymToQtKey_internal(xkb_keysym_t keysym, Qt::KeyboardModifiers mod } else if (keysym >= XKB_KEY_KP_0 && keysym <= XKB_KEY_KP_9) { // numeric keypad keys qtKey = Qt::Key_0 + (keysym - XKB_KEY_KP_0); - } else if (QXkbCommon::isLatin(keysym)) { + } else if (QXkbCommon::isLatin1(keysym)) { qtKey = QXkbCommon::qxkbcommon_xkb_keysym_to_upper(keysym); } else { // check if we have a direct mapping @@ -678,7 +678,7 @@ QList QXkbCommon::possibleKeys(xkb_state *state, const QKeyEvent *event, Qt::KeyboardModifiers neededMods = ModsTbl[i]; if ((modifiers & neededMods) == neededMods) { if (i == 8) { - if (isLatin(baseQtKey)) + if (isLatin1(baseQtKey)) continue; // add a latin key as a fall back key sym = lookupLatinKeysym(state, keycode); @@ -733,7 +733,7 @@ void QXkbCommon::verifyHasLatinLayout(xkb_keymap *keymap) for (xkb_layout_index_t layout = 0; layout < layoutCount; ++layout) { for (xkb_keycode_t code = minKeycode; code < maxKeycode; ++code) { xkb_keymap_key_get_syms_by_level(keymap, code, layout, 0, &keysyms); - if (keysyms && isLatin(keysyms[0])) + if (keysyms && isLatin1(keysyms[0])) nrLatinKeys++; if (nrLatinKeys > 10) // arbitrarily chosen threshold return; @@ -766,7 +766,7 @@ xkb_keysym_t QXkbCommon::lookupLatinKeysym(xkb_state *state, xkb_keycode_t keyco xkb_level_index_t level = xkb_state_key_get_level(state, keycode, layout); if (xkb_keymap_key_get_syms_by_level(keymap, keycode, layout, level, &syms) != 1) continue; - if (isLatin(syms[0])) { + if (isLatin1(syms[0])) { sym = syms[0]; break; } diff --git a/src/platformsupport/input/xkbcommon/qxkbcommon_p.h b/src/platformsupport/input/xkbcommon/qxkbcommon_p.h index 561eae03..8389bd8f 100644 --- a/src/platformsupport/input/xkbcommon/qxkbcommon_p.h +++ b/src/platformsupport/input/xkbcommon/qxkbcommon_p.h @@ -94,8 +94,8 @@ public: static void verifyHasLatinLayout(xkb_keymap *keymap); static xkb_keysym_t lookupLatinKeysym(xkb_state *state, xkb_keycode_t keycode); - static bool isLatin(xkb_keysym_t sym) { - return ((sym >= 'a' && sym <= 'z') || (sym >= 'A' && sym <= 'Z')); + static bool isLatin1(xkb_keysym_t sym) { + return sym <= 0xff; } static bool isKeypad(xkb_keysym_t sym) { return sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9; diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 46746306..27a2526d 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -593,10 +593,6 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event); if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) xi2ProcessTouch(xiDeviceEvent, platformWindow); - else { // When the window cannot be matched, delete it from touchPoints - if (TouchDeviceData *dev = touchDeviceForId(xiDeviceEvent->sourceid)) - dev->touchPoints.remove((xiDeviceEvent->detail % INT_MAX)); - } break; } } else if (xiEnterEvent && !xi2MouseEventsDisabled() && eventListener) { diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index ffda7b6a..abcdce03 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -93,6 +93,8 @@ enum { QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window"); + Q_DECLARE_TYPEINFO(xcb_rectangle_t, Q_PRIMITIVE_TYPE); #undef FocusIn @@ -297,11 +299,6 @@ void QXcbWindow::create() return; } - QPlatformWindow::setGeometry(rect); - - if (platformScreen != currentScreen) - QWindowSystemInterface::handleWindowScreenChanged(window(), platformScreen->QPlatformScreen::screen()); - const QSize minimumSize = windowMinimumSize(); if (rect.width() > 0 || rect.height() > 0) { rect.setWidth(qBound(1, rect.width(), XCOORD_MAX)); @@ -313,6 +310,11 @@ void QXcbWindow::create() rect.setHeight(QHighDpi::toNativePixels(int(defaultWindowHeight), platformScreen->QPlatformScreen::screen())); } + QPlatformWindow::setGeometry(rect); + + if (platformScreen != currentScreen) + QWindowSystemInterface::handleWindowScreenChanged(window(), platformScreen->QPlatformScreen::screen()); + xcb_window_t xcb_parent_id = platformScreen->root(); if (parent()) { xcb_parent_id = static_cast(parent())->xcb_window(); @@ -555,6 +557,7 @@ void QXcbWindow::destroy() } m_mapped = false; + m_recreationReasons = RecreationNotNeeded; if (m_pendingSyncRequest) m_pendingSyncRequest->invalidate(); @@ -564,11 +567,6 @@ void QXcbWindow::setGeometry(const QRect &rect) { QPlatformWindow::setGeometry(rect); - if (shouldDeferTask(Task::SetGeometry)) { - m_deferredGeometry = rect; - return; - } - propagateSizeHints(); QXcbScreen *currentScreen = xcbScreen(); @@ -693,10 +691,12 @@ void QXcbWindow::setVisible(bool visible) void QXcbWindow::show() { - if (shouldDeferTask(Task::Map)) - return; - if (window()->isTopLevel()) { + if (m_recreationReasons != RecreationNotNeeded) { + qCDebug(lcQpaWindow) << "QXcbWindow: need to recreate window" << window() << m_recreationReasons; + create(); + m_recreationReasons = RecreationNotNeeded; + } // update WM_NORMAL_HINTS propagateSizeHints(); @@ -746,10 +746,6 @@ void QXcbWindow::show() void QXcbWindow::hide() { - if (shouldDeferTask(Task::Unmap)) - return; - - m_wmStateValid = false; xcb_unmap_window(xcb_connection(), m_window); // send synthetic UnmapNotify event according to icccm 4.1.4 @@ -909,9 +905,6 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates() void QXcbWindow::setWindowFlags(Qt::WindowFlags flags) { - if (shouldDeferTask(Task::SetWindowFlags)) - return; - Qt::WindowType type = static_cast(int(flags & Qt::WindowType_Mask)); if (type == Qt::ToolTip) @@ -919,6 +912,12 @@ void QXcbWindow::setWindowFlags(Qt::WindowFlags flags) if (type == Qt::Popup) flags |= Qt::X11BypassWindowManagerHint; + Qt::WindowFlags oldflags = window()->flags(); + if ((oldflags & Qt::WindowStaysOnTopHint) != (flags & Qt::WindowStaysOnTopHint)) + m_recreationReasons |= WindowStaysOnTopHintChanged; + if ((oldflags & Qt::WindowStaysOnBottomHint) != (flags & Qt::WindowStaysOnBottomHint)) + m_recreationReasons |= WindowStaysOnBottomHintChanged; + const quint32 mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK; const quint32 values[] = { // XCB_CW_OVERRIDE_REDIRECT @@ -941,8 +940,6 @@ void QXcbWindow::setWindowFlags(Qt::WindowFlags flags) setTransparentForMouseEvents(flags & Qt::WindowTransparentForInput); updateDoesNotAcceptFocus(flags & Qt::WindowDoesNotAcceptFocus); - - m_isWmManagedWindow = !(flags & Qt::X11BypassWindowManagerHint); } void QXcbWindow::setMotifWmHints(Qt::WindowFlags flags) @@ -1142,9 +1139,6 @@ void QXcbWindow::setWindowState(Qt::WindowStates state) if (state == m_windowState) return; - if (shouldDeferTask(Task::SetWindowState)) - return; - // unset old state if (m_windowState & Qt::WindowMinimized) xcb_map_window(xcb_connection(), m_window); @@ -1894,10 +1888,6 @@ void QXcbWindow::handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event) if (event->window == m_window) { m_mapped = false; QWindowSystemInterface::handleExposeEvent(window(), QRegion()); - if (!m_isWmManagedWindow || parent()) { - m_wmStateValid = true; - handleDeferredTasks(); - } } } @@ -2212,98 +2202,30 @@ void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event) handleLeaveNotifyEvent(event->root_x, event->root_y, event->mode, event->detail, event->time); } -bool QXcbWindow::shouldDeferTask(Task task) -{ - if (m_wmStateValid) - return false; - - m_deferredTasks.append(task); - return true; -} - -void QXcbWindow::handleDeferredTasks() -{ - Q_ASSERT(m_wmStateValid == true); - if (m_deferredTasks.isEmpty()) - return; - - bool map = false; - bool unmap = false; - - QVector tasks; - for (auto taskIt = m_deferredTasks.rbegin(); taskIt != m_deferredTasks.rend(); ++taskIt) { - if (!tasks.contains(*taskIt)) - tasks.prepend(*taskIt); - } - - for (Task task : tasks) { - switch (task) { - case Task::Map: - map = true; - unmap = false; - break; - case Task::Unmap: - unmap = true; - map = false; - break; - case Task::SetGeometry: - setGeometry(m_deferredGeometry); - break; - case Task::SetWindowFlags: - setWindowFlags(window()->flags()); - break; - case Task::SetWindowState: - setWindowState(window()->windowState()); - break; - } - } - m_deferredTasks.clear(); - - if (map) { - Q_ASSERT(unmap == false); - show(); - } - if (unmap) { - Q_ASSERT(map == false); - hide(); - } -} - void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) { connection()->setTime(event->time); - const bool wmStateChanged = event->atom == atom(QXcbAtom::WM_STATE); - const bool netWmStateChanged = event->atom == atom(QXcbAtom::_NET_WM_STATE); - if (netWmStateChanged || wmStateChanged) { - if (wmStateChanged && !m_wmStateValid && m_isWmManagedWindow) { - // ICCCM 4.1.4 - // Clients that want to re-use a client window (e.g. by mapping it again) - // after withdrawing it must wait for the withdrawal to be complete before - // proceeding. The preferred method for doing this is for clients to wait for - // a window manager to update or remove the WM_STATE property. - m_wmStateValid = true; - handleDeferredTasks(); - } - if (event->state == XCB_PROPERTY_DELETE) + const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE; + + if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) { + if (propertyDeleted) return; - if (wmStateChanged) { + Qt::WindowStates newState = Qt::WindowNoState; + + if (event->atom == atom(QXcbAtom::WM_STATE)) { // WM_STATE: Quick check for 'Minimize'. auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), 0, m_window, atom(QXcbAtom::WM_STATE), XCB_ATOM_ANY, 0, 1024); if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::WM_STATE)) { - auto data = static_cast(xcb_get_property_value(reply.get())); - if (reply->length != 0) { - const bool changedToWithdrawn = data[0] == XCB_ICCCM_WM_STATE_WITHDRAWN; - const bool changedToIconic = data[0] == XCB_ICCCM_WM_STATE_ICONIC; - m_minimized = changedToIconic || (changedToWithdrawn && m_minimized); - } + const quint32 *data = (const quint32 *)xcb_get_property_value(reply.get()); + if (reply->length != 0) + m_minimized = (data[0] == XCB_ICCCM_WM_STATE_ICONIC + || (data[0] == XCB_ICCCM_WM_STATE_WITHDRAWN && m_minimized)); } } - // _NET_WM_STATE handling - Qt::WindowStates newState = Qt::WindowNoState; const NetWmStates states = netWmStates(); // _NET_WM_STATE_HIDDEN should be set by the Window Manager to indicate that a window would // not be visible on the screen if its desktop/viewport were active and its coordinates were @@ -2325,6 +2247,7 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev if ((m_windowState & Qt::WindowMinimized) && connection()->mouseGrabber() == this) connection()->setMouseGrabber(nullptr); } + return; } else if (event->atom == atom(QXcbAtom::_NET_FRAME_EXTENTS)) { m_dirtyFrameMargins = true; } diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 55af9279..8de486c6 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -74,13 +74,12 @@ public: Q_DECLARE_FLAGS(NetWmStates, NetWmState) - enum Task { - Map, - Unmap, - SetGeometry, - SetWindowFlags, - SetWindowState + enum RecreationReason { + RecreationNotNeeded = 0, + WindowStaysOnTopHintChanged = 0x1, + WindowStaysOnBottomHintChanged = 0x2 }; + Q_DECLARE_FLAGS(RecreationReasons, RecreationReason) QXcbWindow(QWindow *window); ~QXcbWindow(); @@ -151,9 +150,6 @@ public: QXcbWindow *toWindow() override; - bool shouldDeferTask(Task task); - void handleDeferredTasks(); - void handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global, Qt::KeyboardModifiers modifiers, QEvent::Type type, Qt::MouseEventSource source); @@ -293,10 +289,7 @@ protected: qreal m_sizeHintsScaleFactor = 1.0; - bool m_wmStateValid = true; - QVector m_deferredTasks; - bool m_isWmManagedWindow = true; - QRect m_deferredGeometry; + RecreationReasons m_recreationReasons = RecreationNotNeeded; }; class QXcbForeignWindow : public QXcbWindow diff --git a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp index 5f51de38..6cac60d0 100644 --- a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp +++ b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp @@ -92,23 +92,39 @@ inline static QString fromSQLTCHAR(const QVarLengthArray& input, int s return result; } +template +void toSQLTCHARImpl(QVarLengthArray &result, const QString &input); // primary template undefined + +template +void do_append(QVarLengthArray &result, const Container &c) +{ + result.append(reinterpret_cast(c.data()), c.size()); +} + +template <> +void toSQLTCHARImpl<1>(QVarLengthArray &result, const QString &input) +{ + const auto u8 = input.toUtf8(); + do_append(result, u8); +} + +template <> +void toSQLTCHARImpl<2>(QVarLengthArray &result, const QString &input) +{ + do_append(result, input); +} + +template <> +void toSQLTCHARImpl<4>(QVarLengthArray &result, const QString &input) +{ + const auto u32 = input.toUcs4(); + do_append(result, u32); +} + inline static QVarLengthArray toSQLTCHAR(const QString &input) { QVarLengthArray result; - result.resize(input.size()); - switch(sizeof(SQLTCHAR)) { - case 1: - memcpy(result.data(), input.toUtf8().data(), input.size()); - break; - case 2: - memcpy(result.data(), input.unicode(), input.size() * 2); - break; - case 4: - memcpy(result.data(), input.toUcs4().data(), input.size() * 4); - break; - default: - qCritical("sizeof(SQLTCHAR) is %d. Don't know how to handle this.", int(sizeof(SQLTCHAR))); - } + toSQLTCHARImpl(result, input); result.append(0); // make sure it's null terminated, doesn't matter if it already is, it does if it isn't. return result; } @@ -763,6 +779,14 @@ QChar QODBCDriverPrivate::quoteChar() return quote; } +static SQLRETURN qt_string_SQLSetConnectAttr(SQLHDBC handle, SQLINTEGER attr, const QString &val) +{ + auto encoded = toSQLTCHAR(val); + return SQLSetConnectAttr(handle, attr, + encoded.data(), + SQLINTEGER(encoded.size() * sizeof(SQLTCHAR))); // size in bytes +} + bool QODBCDriverPrivate::setConnectionOptions(const QString& connOpts) { @@ -798,10 +822,7 @@ bool QODBCDriverPrivate::setConnectionOptions(const QString& connOpts) v = val.toUInt(); r = SQLSetConnectAttr(hDbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER) size_t(v), 0); } else if (opt.toUpper() == QLatin1String("SQL_ATTR_CURRENT_CATALOG")) { - val.utf16(); // 0 terminate - r = SQLSetConnectAttr(hDbc, SQL_ATTR_CURRENT_CATALOG, - toSQLTCHAR(val).data(), - val.length()*sizeof(SQLTCHAR)); + r = qt_string_SQLSetConnectAttr(hDbc, SQL_ATTR_CURRENT_CATALOG, val); } else if (opt.toUpper() == QLatin1String("SQL_ATTR_METADATA_ID")) { if (val.toUpper() == QLatin1String("SQL_TRUE")) { v = SQL_TRUE; @@ -816,10 +837,7 @@ bool QODBCDriverPrivate::setConnectionOptions(const QString& connOpts) v = val.toUInt(); r = SQLSetConnectAttr(hDbc, SQL_ATTR_PACKET_SIZE, (SQLPOINTER) size_t(v), 0); } else if (opt.toUpper() == QLatin1String("SQL_ATTR_TRACEFILE")) { - val.utf16(); // 0 terminate - r = SQLSetConnectAttr(hDbc, SQL_ATTR_TRACEFILE, - toSQLTCHAR(val).data(), - val.length()*sizeof(SQLTCHAR)); + r = qt_string_SQLSetConnectAttr(hDbc, SQL_ATTR_TRACEFILE, val); } else if (opt.toUpper() == QLatin1String("SQL_ATTR_TRACE")) { if (val.toUpper() == QLatin1String("SQL_OPT_TRACE_OFF")) { v = SQL_OPT_TRACE_OFF; @@ -1022,9 +1040,12 @@ bool QODBCResult::reset (const QString& query) return false; } - r = SQLExecDirect(d->hStmt, - toSQLTCHAR(query).data(), - (SQLINTEGER) query.length()); + { + auto encoded = toSQLTCHAR(query); + r = SQLExecDirect(d->hStmt, + encoded.data(), + SQLINTEGER(encoded.size())); + } if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO && r!= SQL_NO_DATA) { setLastError(qMakeError(QCoreApplication::translate("QODBCResult", "Unable to execute statement"), QSqlError::StatementError, d)); @@ -1371,9 +1392,12 @@ bool QODBCResult::prepare(const QString& query) return false; } - r = SQLPrepare(d->hStmt, - toSQLTCHAR(query).data(), - (SQLINTEGER) query.length()); + { + auto encoded = toSQLTCHAR(query); + r = SQLPrepare(d->hStmt, + encoded.data(), + SQLINTEGER(encoded.size())); + } if (r != SQL_SUCCESS) { setLastError(qMakeError(QCoreApplication::translate("QODBCResult", @@ -1401,7 +1425,7 @@ bool QODBCResult::exec() SQLCloseCursor(d->hStmt); QVector& values = boundValues(); - QVector tmpStorage(values.count(), QByteArray()); // holds temporary buffers + QVector tmpStorage(values.count(), QByteArray()); // targets for SQLBindParameter() QVarLengthArray indicators(values.count()); memset(indicators.data(), 0, indicators.size() * sizeof(SQLLEN)); @@ -1580,35 +1604,36 @@ bool QODBCResult::exec() case QVariant::String: if (d->unicode) { QByteArray &ba = tmpStorage[i]; - QString str = val.toString(); + { + const auto encoded = toSQLTCHAR(val.toString()); + ba = QByteArray(reinterpret_cast(encoded.data()), + encoded.size() * sizeof(SQLTCHAR)); + } + if (*ind != SQL_NULL_DATA) - *ind = str.length() * sizeof(SQLTCHAR); - int strSize = str.length() * sizeof(SQLTCHAR); + *ind = ba.size(); if (bindValueType(i) & QSql::Out) { - const QVarLengthArray a(toSQLTCHAR(str)); - ba = QByteArray((const char *)a.constData(), a.size() * sizeof(SQLTCHAR)); r = SQLBindParameter(d->hStmt, i + 1, qParamType[bindValueType(i) & QSql::InOut], SQL_C_TCHAR, - strSize > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR, + ba.size() > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR, 0, // god knows... don't change this! 0, - ba.data(), + const_cast(ba.constData()), // don't detach ba.size(), ind); break; } - ba = QByteArray ((const char *)toSQLTCHAR(str).constData(), str.size()*sizeof(SQLTCHAR)); r = SQLBindParameter(d->hStmt, i + 1, qParamType[bindValueType(i) & QSql::InOut], SQL_C_TCHAR, - strSize > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR, - strSize, + ba.size() > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR, + ba.size(), 0, - const_cast(ba.constData()), + const_cast(ba.constData()), // don't detach ba.size(), ind); break; @@ -1716,10 +1741,11 @@ bool QODBCResult::exec() case QVariant::String: if (d->unicode) { if (bindValueType(i) & QSql::Out) { - const QByteArray &first = tmpStorage.at(i); - QVarLengthArray array; - array.append((const SQLTCHAR *)first.constData(), first.size()); - values[i] = fromSQLTCHAR(array, first.size()/sizeof(SQLTCHAR)); + const QByteArray &bytes = tmpStorage.at(i); + const auto strSize = bytes.size() / int(sizeof(SQLTCHAR)); + QVarLengthArray string(strSize); + memcpy(string.data(), bytes.data(), strSize * sizeof(SQLTCHAR)); + values[i] = fromSQLTCHAR(string); } break; } @@ -1966,14 +1992,16 @@ bool QODBCDriver::open(const QString & db, SQLSMALLINT cb; QVarLengthArray connOut(1024); memset(connOut.data(), 0, connOut.size() * sizeof(SQLTCHAR)); - r = SQLDriverConnect(d->hDbc, - NULL, - toSQLTCHAR(connQStr).data(), - (SQLSMALLINT)connQStr.length(), - connOut.data(), - 1024, - &cb, - /*SQL_DRIVER_NOPROMPT*/0); + { + auto encoded = toSQLTCHAR(connQStr); + r = SQLDriverConnect(d->hDbc, + nullptr, + encoded.data(), SQLSMALLINT(encoded.size()), + connOut.data(), + 1024, + &cb, + /*SQL_DRIVER_NOPROMPT*/0); + } if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) { setLastError(qMakeError(tr("Unable to connect"), QSqlError::ConnectionError, d)); @@ -2352,17 +2380,15 @@ QStringList QODBCDriver::tables(QSql::TableType type) const if (tableType.isEmpty()) return tl; - QString joinedTableTypeString = tableType.join(QLatin1Char(',')); + { + auto joinedTableTypeString = toSQLTCHAR(tableType.join(u',')); - r = SQLTables(hStmt, - NULL, - 0, - NULL, - 0, - NULL, - 0, - toSQLTCHAR(joinedTableTypeString).data(), - joinedTableTypeString.length() /* characters, not bytes */); + r = SQLTables(hStmt, + nullptr, 0, + nullptr, 0, + nullptr, 0, + joinedTableTypeString.data(), joinedTableTypeString.size()); + } if (r != SQL_SUCCESS) qSqlWarning(QLatin1String("QODBCDriver::tables Unable to execute table list"), d); @@ -2436,28 +2462,30 @@ QSqlIndex QODBCDriver::primaryIndex(const QString& tablename) const SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY, SQL_IS_UINTEGER); - r = SQLPrimaryKeys(hStmt, - catalog.length() == 0 ? NULL : toSQLTCHAR(catalog).data(), - catalog.length(), - schema.length() == 0 ? NULL : toSQLTCHAR(schema).data(), - schema.length(), - toSQLTCHAR(table).data(), - table.length() /* in characters, not in bytes */); + { + auto c = toSQLTCHAR(catalog); + auto s = toSQLTCHAR(schema); + auto t = toSQLTCHAR(table); + r = SQLPrimaryKeys(hStmt, + catalog.isEmpty() ? nullptr : c.data(), c.size(), + schema.isEmpty() ? nullptr : s.data(), s.size(), + t.data(), t.size()); + } // if the SQLPrimaryKeys() call does not succeed (e.g the driver // does not support it) - try an alternative method to get hold of // the primary index (e.g MS Access and FoxPro) if (r != SQL_SUCCESS) { - r = SQLSpecialColumns(hStmt, - SQL_BEST_ROWID, - catalog.length() == 0 ? NULL : toSQLTCHAR(catalog).data(), - catalog.length(), - schema.length() == 0 ? NULL : toSQLTCHAR(schema).data(), - schema.length(), - toSQLTCHAR(table).data(), - table.length(), - SQL_SCOPE_CURROW, - SQL_NULLABLE); + auto c = toSQLTCHAR(catalog); + auto s = toSQLTCHAR(schema); + auto t = toSQLTCHAR(table); + r = SQLSpecialColumns(hStmt, + SQL_BEST_ROWID, + catalog.isEmpty() ? nullptr : c.data(), c.size(), + schema.isEmpty() ? nullptr : s.data(), s.size(), + t.data(), t.size(), + SQL_SCOPE_CURROW, + SQL_NULLABLE); if (r != SQL_SUCCESS) { qSqlWarning(QLatin1String("QODBCDriver::primaryIndex: Unable to execute primary key list"), d); @@ -2538,15 +2566,17 @@ QSqlRecord QODBCDriver::record(const QString& tablename) const SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY, SQL_IS_UINTEGER); - r = SQLColumns(hStmt, - catalog.length() == 0 ? NULL : toSQLTCHAR(catalog).data(), - catalog.length(), - schema.length() == 0 ? NULL : toSQLTCHAR(schema).data(), - schema.length(), - toSQLTCHAR(table).data(), - table.length(), - NULL, - 0); + { + auto c = toSQLTCHAR(catalog); + auto s = toSQLTCHAR(schema); + auto t = toSQLTCHAR(table); + r = SQLColumns(hStmt, + catalog.isEmpty() ? nullptr : c.data(), c.size(), + schema.isEmpty() ? nullptr : s.data(), s.size(), + t.data(), t.size(), + nullptr, + 0); + } if (r != SQL_SUCCESS) qSqlWarning(QLatin1String("QODBCDriver::record: Unable to execute column list"), d); diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index a23d8b79..2809bebc 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -624,6 +624,29 @@ void QMenuPrivate::hideMenu(QMenu *menu) menu->d_func()->causedPopup.widget = nullptr; } +QWindow *QMenuPrivate::transientParentWindow() const +{ + Q_Q(const QMenu); + if (const QWidget *parent = q->nativeParentWidget()) { + if (parent->windowHandle()) + return parent->windowHandle(); + } + + if (const QWindow *w = q->windowHandle()) { + if (w->transientParent()) + return w->transientParent(); + } + + if (causedPopup.widget) { + if (const QWidget *w = causedPopup.widget.data()) { + if (const QWidget *ww = w->window()) + return ww->windowHandle(); + } + } + + return nullptr; +} + void QMenuPrivate::popupAction(QAction *action, int delay, bool activateFirst) { Q_Q(QMenu); @@ -3060,6 +3083,8 @@ QMenu::event(QEvent *e) d->sloppyState.reset(); if (d->currentAction) d->popupAction(d->currentAction, 0, false); + if (isWindow() && window() && window()->windowHandle() && !window()->windowHandle()->transientParent()) + window()->windowHandle()->setTransientParent(d->transientParentWindow()); break; #ifndef QT_NO_TOOLTIP case QEvent::ToolTip: diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h index 3871d676..fa3929ea 100644 --- a/src/widgets/widgets/qmenu_p.h +++ b/src/widgets/widgets/qmenu_p.h @@ -440,6 +440,7 @@ public: QMenuCaused causedPopup; void hideUpToMenuBar(); void hideMenu(QMenu *menu); + QWindow *transientParentWindow() const; //index mappings inline QAction *actionAt(int i) const { return q_func()->actions().at(i); } diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp index a3b8ef78..4955cebd 100644 --- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp @@ -1498,7 +1498,7 @@ void tst_QApplication::desktopSettingsAware() environment += QLatin1String("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM=1"); testProcess.setEnvironment(environment); #endif - testProcess.start("desktopsettingsaware_helper"); + testProcess.start("./desktopsettingsaware_helper"); QVERIFY2(testProcess.waitForStarted(), qPrintable(QString::fromLatin1("Cannot start 'desktopsettingsaware_helper': %1").arg(testProcess.errorString()))); QVERIFY(testProcess.waitForFinished(10000)); @@ -2452,7 +2452,7 @@ void tst_QApplication::qtbug_12673() #if QT_CONFIG(process) QProcess testProcess; QStringList arguments; - testProcess.start("modal_helper", arguments); + testProcess.start("./modal_helper", arguments); QVERIFY2(testProcess.waitForStarted(), qPrintable(QString::fromLatin1("Cannot start 'modal_helper': %1").arg(testProcess.errorString()))); QVERIFY(testProcess.waitForFinished(20000));