!5 处理编译错误2

Merge pull request !5 from hanpinlong/openkylin/yangtze
This commit is contained in:
hanpinlong 2023-05-05 09:27:51 +00:00 committed by Gitee
commit 1ffba57fcd
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
20 changed files with 268 additions and 246 deletions

2
debian/changelog vendored
View File

@ -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 * rebuild

View File

@ -176,6 +176,39 @@ void ThreadEngineBase::startSingleThreaded()
finish(); 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() void ThreadEngineBase::startThread()
{ {
startThreadInternal(); startThreadInternal();

View File

@ -91,6 +91,7 @@ public:
ThreadEngineBase(); ThreadEngineBase();
virtual ~ThreadEngineBase(); virtual ~ThreadEngineBase();
void startSingleThreaded(); void startSingleThreaded();
void startBlocking();
void startThread(); void startThread();
bool isCanceled(); bool isCanceled();
void waitForResume(); void waitForResume();
@ -143,6 +144,15 @@ public:
return result(); 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. // Runs the user algorithm using multiple threads.
// Does not block, returns a future. // Does not block, returns a future.
QFuture<T> startAsynchronously() QFuture<T> startAsynchronously()
@ -223,6 +233,13 @@ class ThreadEngineStarter : public ThreadEngineStarterBase<T>
public: public:
ThreadEngineStarter(TypedThreadEngine *eng) ThreadEngineStarter(TypedThreadEngine *eng)
: Base(eng) { } : Base(eng) { }
T startBlocking()
{
T t = *this->threadEngine->startBlocking();
delete this->threadEngine;
return t;
}
}; };
// Full template specialization where T is void. // Full template specialization where T is void.
@ -232,6 +249,12 @@ class ThreadEngineStarter<void> : public ThreadEngineStarterBase<void>
public: public:
ThreadEngineStarter(ThreadEngine<void> *_threadEngine) ThreadEngineStarter(ThreadEngine<void> *_threadEngine)
: ThreadEngineStarterBase<void>(_threadEngine) {} : ThreadEngineStarterBase<void>(_threadEngine) {}
void startBlocking()
{
this->threadEngine->startBlocking();
delete this->threadEngine;
}
}; };
//! [qtconcurrentthreadengine-1] //! [qtconcurrentthreadengine-1]

View File

@ -515,9 +515,9 @@ QImageReaderPrivate::QImageReaderPrivate(QImageReader *qq)
*/ */
QImageReaderPrivate::~QImageReaderPrivate() QImageReaderPrivate::~QImageReaderPrivate()
{ {
delete handler;
if (deleteDevice) if (deleteDevice)
delete device; delete device;
delete handler;
} }
/*! /*!
@ -774,12 +774,12 @@ bool QImageReader::decideFormatFromContent() const
*/ */
void QImageReader::setDevice(QIODevice *device) void QImageReader::setDevice(QIODevice *device)
{ {
delete d->handler;
d->handler = nullptr;
if (d->device && d->deleteDevice) if (d->device && d->deleteDevice)
delete d->device; delete d->device;
d->device = device; d->device = device;
d->deleteDevice = false; d->deleteDevice = false;
delete d->handler;
d->handler = nullptr;
d->text.clear(); d->text.clear();
} }

View File

@ -349,9 +349,9 @@ QImageWriter::QImageWriter(const QString &fileName, const QByteArray &format)
*/ */
QImageWriter::~QImageWriter() QImageWriter::~QImageWriter()
{ {
delete d->handler;
if (d->deleteDevice) if (d->deleteDevice)
delete d->device; delete d->device;
delete d->handler;
delete d; delete d;
} }
@ -396,13 +396,13 @@ QByteArray QImageWriter::format() const
*/ */
void QImageWriter::setDevice(QIODevice *device) void QImageWriter::setDevice(QIODevice *device)
{ {
delete d->handler;
d->handler = nullptr;
if (d->device && d->deleteDevice) if (d->device && d->deleteDevice)
delete d->device; delete d->device;
d->device = device; d->device = device;
d->deleteDevice = false; d->deleteDevice = false;
delete d->handler;
d->handler = nullptr;
} }
/*! /*!

View File

@ -1412,14 +1412,7 @@ void QGuiApplicationPrivate::createPlatformIntegration()
if (sessionType == QByteArrayLiteral("x11") && !platformName.contains(QByteArrayLiteral("xcb"))) { if (sessionType == QByteArrayLiteral("x11") && !platformName.contains(QByteArrayLiteral("xcb"))) {
platformName = QByteArrayLiteral("xcb"); platformName = QByteArrayLiteral("xcb");
} else if (sessionType == QByteArrayLiteral("wayland") && !platformName.contains(QByteArrayLiteral("wayland"))) { } else if (sessionType == QByteArrayLiteral("wayland") && !platformName.contains(QByteArrayLiteral("wayland"))) {
QByteArray currentDesktop = qgetenv("XDG_CURRENT_DESKTOP").toLower(); platformName = QByteArrayLiteral("wayland");
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");
}
} }
} }
#ifdef QT_QPA_DEFAULT_PLATFORM_NAME #ifdef QT_QPA_DEFAULT_PLATFORM_NAME
@ -3064,8 +3057,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
QEvent::Type mouseEventType = QEvent::MouseMove; QEvent::Type mouseEventType = QEvent::MouseMove;
Qt::MouseButton button = Qt::NoButton; Qt::MouseButton button = Qt::NoButton;
Qt::MouseButtons buttons = Qt::LeftButton; Qt::MouseButtons buttons = Qt::LeftButton;
if ((eventType == QEvent::TouchBegin && m_fakeMouseSourcePointId < 0) if (eventType == QEvent::TouchBegin && m_fakeMouseSourcePointId < 0)
|| (touchPoints.count() == 1 && m_fakeMouseSourcePointId != touchPoints.first().id()))
m_fakeMouseSourcePointId = touchPoints.first().id(); m_fakeMouseSourcePointId = touchPoints.first().id();
for (const auto &touchPoint : touchPoints) { for (const auto &touchPoint : touchPoints) {
if (touchPoint.id() == m_fakeMouseSourcePointId) { if (touchPoint.id() == m_fakeMouseSourcePointId) {

View File

@ -455,7 +455,7 @@ init_context:
} }
// Enable bug workarounds. // 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); q_SSL_CTX_set_options(sslContext->ctx, options);
// Tell OpenSSL to release memory early // Tell OpenSSL to release memory early

View File

@ -550,9 +550,9 @@ static void q_loadCiphersForConnection(SSL *connection, QList<QSslCipher> &ciphe
// Defined in qsslsocket.cpp // Defined in qsslsocket.cpp
void q_setDefaultDtlsCiphers(const QList<QSslCipher> &ciphers); void q_setDefaultDtlsCiphers(const QList<QSslCipher> &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) if (protocol == QSsl::TlsV1SslV3)
options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3; options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;
else if (protocol == QSsl::SecureProtocols) else if (protocol == QSsl::SecureProtocols)

View File

@ -107,6 +107,12 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
typedef uint64_t qssloptions;
#else
typedef unsigned long qssloptions;
#endif
struct QSslErrorEntry { struct QSslErrorEntry {
int code; int code;
int depth; int depth;
@ -171,7 +177,7 @@ public:
QVector<QSslError> ocspErrors; QVector<QSslError> ocspErrors;
QByteArray ocspResponseDer; 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 QSslCipher QSslCipher_from_SSL_CIPHER(const SSL_CIPHER *cipher);
static QList<QSslCertificate> STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509); static QList<QSslCertificate> STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509);
static QList<QSslError> verify(const QList<QSslCertificate> &certificateChain, const QString &hostName); static QList<QSslError> verify(const QList<QSslCertificate> &certificateChain, const QString &hostName);

View File

@ -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) 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) 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) 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) 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) DEFINEFUNC2(void, SSL_CTX_set_security_level, SSL_CTX *ctx, ctx, int level, level, return, return)
#ifdef TLS1_3_VERSION #ifdef TLS1_3_VERSION

View File

@ -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_free(OPENSSL_STACK *a);
Q_AUTOTEST_EXPORT void * q_OPENSSL_sk_value(OPENSSL_STACK *a, int b); Q_AUTOTEST_EXPORT void * q_OPENSSL_sk_value(OPENSSL_STACK *a, int b);
int q_SSL_session_reused(SSL *a); 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); 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_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); size_t q_SSL_SESSION_get_master_key(const SSL_SESSION *session, unsigned char *out, size_t outlen);

View File

@ -471,7 +471,7 @@ QVector<xkb_keysym_t> QXkbCommon::toKeysym(QKeyEvent *event)
} else if (event->modifiers() & Qt::KeypadModifier) { } else if (event->modifiers() & Qt::KeypadModifier) {
if (qtKey >= Qt::Key_0 && qtKey <= Qt::Key_9) if (qtKey >= Qt::Key_0 && qtKey <= Qt::Key_9)
keysyms.append(XKB_KEY_KP_0 + (qtKey - Qt::Key_0)); 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); 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 // With standard shortcuts we should prefer a latin character, this is
// for checks like "some qkeyevent == QKeySequence::Copy" to work even // for checks like "some qkeyevent == QKeySequence::Copy" to work even
// when using for example 'russian' keyboard layout. // when using for example 'russian' keyboard layout.
if (!QXkbCommon::isLatin(keysym)) { if (!QXkbCommon::isLatin1(keysym)) {
xkb_keysym_t latinKeysym = QXkbCommon::lookupLatinKeysym(state, code); xkb_keysym_t latinKeysym = QXkbCommon::lookupLatinKeysym(state, code);
if (latinKeysym != XKB_KEY_NoSymbol) if (latinKeysym != XKB_KEY_NoSymbol)
keysym = latinKeysym; 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) { } else if (keysym >= XKB_KEY_KP_0 && keysym <= XKB_KEY_KP_9) {
// numeric keypad keys // numeric keypad keys
qtKey = Qt::Key_0 + (keysym - XKB_KEY_KP_0); 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); qtKey = QXkbCommon::qxkbcommon_xkb_keysym_to_upper(keysym);
} else { } else {
// check if we have a direct mapping // check if we have a direct mapping
@ -678,7 +678,7 @@ QList<int> QXkbCommon::possibleKeys(xkb_state *state, const QKeyEvent *event,
Qt::KeyboardModifiers neededMods = ModsTbl[i]; Qt::KeyboardModifiers neededMods = ModsTbl[i];
if ((modifiers & neededMods) == neededMods) { if ((modifiers & neededMods) == neededMods) {
if (i == 8) { if (i == 8) {
if (isLatin(baseQtKey)) if (isLatin1(baseQtKey))
continue; continue;
// add a latin key as a fall back key // add a latin key as a fall back key
sym = lookupLatinKeysym(state, keycode); 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_layout_index_t layout = 0; layout < layoutCount; ++layout) {
for (xkb_keycode_t code = minKeycode; code < maxKeycode; ++code) { for (xkb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
xkb_keymap_key_get_syms_by_level(keymap, code, layout, 0, &keysyms); xkb_keymap_key_get_syms_by_level(keymap, code, layout, 0, &keysyms);
if (keysyms && isLatin(keysyms[0])) if (keysyms && isLatin1(keysyms[0]))
nrLatinKeys++; nrLatinKeys++;
if (nrLatinKeys > 10) // arbitrarily chosen threshold if (nrLatinKeys > 10) // arbitrarily chosen threshold
return; 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); 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) if (xkb_keymap_key_get_syms_by_level(keymap, keycode, layout, level, &syms) != 1)
continue; continue;
if (isLatin(syms[0])) { if (isLatin1(syms[0])) {
sym = syms[0]; sym = syms[0];
break; break;
} }

View File

@ -94,8 +94,8 @@ public:
static void verifyHasLatinLayout(xkb_keymap *keymap); static void verifyHasLatinLayout(xkb_keymap *keymap);
static xkb_keysym_t lookupLatinKeysym(xkb_state *state, xkb_keycode_t keycode); static xkb_keysym_t lookupLatinKeysym(xkb_state *state, xkb_keycode_t keycode);
static bool isLatin(xkb_keysym_t sym) { static bool isLatin1(xkb_keysym_t sym) {
return ((sym >= 'a' && sym <= 'z') || (sym >= 'A' && sym <= 'Z')); return sym <= 0xff;
} }
static bool isKeypad(xkb_keysym_t sym) { static bool isKeypad(xkb_keysym_t sym) {
return sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9; return sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9;

View File

@ -593,10 +593,6 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event); fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event);
if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event))
xi2ProcessTouch(xiDeviceEvent, platformWindow); 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; break;
} }
} else if (xiEnterEvent && !xi2MouseEventsDisabled() && eventListener) { } else if (xiEnterEvent && !xi2MouseEventsDisabled() && eventListener) {

View File

@ -93,6 +93,8 @@ enum {
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window");
Q_DECLARE_TYPEINFO(xcb_rectangle_t, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(xcb_rectangle_t, Q_PRIMITIVE_TYPE);
#undef FocusIn #undef FocusIn
@ -297,11 +299,6 @@ void QXcbWindow::create()
return; return;
} }
QPlatformWindow::setGeometry(rect);
if (platformScreen != currentScreen)
QWindowSystemInterface::handleWindowScreenChanged(window(), platformScreen->QPlatformScreen::screen());
const QSize minimumSize = windowMinimumSize(); const QSize minimumSize = windowMinimumSize();
if (rect.width() > 0 || rect.height() > 0) { if (rect.width() > 0 || rect.height() > 0) {
rect.setWidth(qBound(1, rect.width(), XCOORD_MAX)); rect.setWidth(qBound(1, rect.width(), XCOORD_MAX));
@ -313,6 +310,11 @@ void QXcbWindow::create()
rect.setHeight(QHighDpi::toNativePixels(int(defaultWindowHeight), platformScreen->QPlatformScreen::screen())); 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(); xcb_window_t xcb_parent_id = platformScreen->root();
if (parent()) { if (parent()) {
xcb_parent_id = static_cast<QXcbWindow *>(parent())->xcb_window(); xcb_parent_id = static_cast<QXcbWindow *>(parent())->xcb_window();
@ -555,6 +557,7 @@ void QXcbWindow::destroy()
} }
m_mapped = false; m_mapped = false;
m_recreationReasons = RecreationNotNeeded;
if (m_pendingSyncRequest) if (m_pendingSyncRequest)
m_pendingSyncRequest->invalidate(); m_pendingSyncRequest->invalidate();
@ -564,11 +567,6 @@ void QXcbWindow::setGeometry(const QRect &rect)
{ {
QPlatformWindow::setGeometry(rect); QPlatformWindow::setGeometry(rect);
if (shouldDeferTask(Task::SetGeometry)) {
m_deferredGeometry = rect;
return;
}
propagateSizeHints(); propagateSizeHints();
QXcbScreen *currentScreen = xcbScreen(); QXcbScreen *currentScreen = xcbScreen();
@ -693,10 +691,12 @@ void QXcbWindow::setVisible(bool visible)
void QXcbWindow::show() void QXcbWindow::show()
{ {
if (shouldDeferTask(Task::Map))
return;
if (window()->isTopLevel()) { 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 // update WM_NORMAL_HINTS
propagateSizeHints(); propagateSizeHints();
@ -746,10 +746,6 @@ void QXcbWindow::show()
void QXcbWindow::hide() void QXcbWindow::hide()
{ {
if (shouldDeferTask(Task::Unmap))
return;
m_wmStateValid = false;
xcb_unmap_window(xcb_connection(), m_window); xcb_unmap_window(xcb_connection(), m_window);
// send synthetic UnmapNotify event according to icccm 4.1.4 // send synthetic UnmapNotify event according to icccm 4.1.4
@ -909,9 +905,6 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates()
void QXcbWindow::setWindowFlags(Qt::WindowFlags flags) void QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
{ {
if (shouldDeferTask(Task::SetWindowFlags))
return;
Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask)); Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
if (type == Qt::ToolTip) if (type == Qt::ToolTip)
@ -919,6 +912,12 @@ void QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
if (type == Qt::Popup) if (type == Qt::Popup)
flags |= Qt::X11BypassWindowManagerHint; 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 mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
const quint32 values[] = { const quint32 values[] = {
// XCB_CW_OVERRIDE_REDIRECT // XCB_CW_OVERRIDE_REDIRECT
@ -941,8 +940,6 @@ void QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
setTransparentForMouseEvents(flags & Qt::WindowTransparentForInput); setTransparentForMouseEvents(flags & Qt::WindowTransparentForInput);
updateDoesNotAcceptFocus(flags & Qt::WindowDoesNotAcceptFocus); updateDoesNotAcceptFocus(flags & Qt::WindowDoesNotAcceptFocus);
m_isWmManagedWindow = !(flags & Qt::X11BypassWindowManagerHint);
} }
void QXcbWindow::setMotifWmHints(Qt::WindowFlags flags) void QXcbWindow::setMotifWmHints(Qt::WindowFlags flags)
@ -1142,9 +1139,6 @@ void QXcbWindow::setWindowState(Qt::WindowStates state)
if (state == m_windowState) if (state == m_windowState)
return; return;
if (shouldDeferTask(Task::SetWindowState))
return;
// unset old state // unset old state
if (m_windowState & Qt::WindowMinimized) if (m_windowState & Qt::WindowMinimized)
xcb_map_window(xcb_connection(), m_window); 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) { if (event->window == m_window) {
m_mapped = false; m_mapped = false;
QWindowSystemInterface::handleExposeEvent(window(), QRegion()); 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); 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<Task> 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) void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *event)
{ {
connection()->setTime(event->time); connection()->setTime(event->time);
const bool wmStateChanged = event->atom == atom(QXcbAtom::WM_STATE); const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE;
const bool netWmStateChanged = event->atom == atom(QXcbAtom::_NET_WM_STATE);
if (netWmStateChanged || wmStateChanged) { if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) {
if (wmStateChanged && !m_wmStateValid && m_isWmManagedWindow) { if (propertyDeleted)
// 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)
return; 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(), auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(),
0, m_window, atom(QXcbAtom::WM_STATE), 0, m_window, atom(QXcbAtom::WM_STATE),
XCB_ATOM_ANY, 0, 1024); XCB_ATOM_ANY, 0, 1024);
if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::WM_STATE)) { if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::WM_STATE)) {
auto data = static_cast<const quint32 *>(xcb_get_property_value(reply.get())); const quint32 *data = (const quint32 *)xcb_get_property_value(reply.get());
if (reply->length != 0) { if (reply->length != 0)
const bool changedToWithdrawn = data[0] == XCB_ICCCM_WM_STATE_WITHDRAWN; m_minimized = (data[0] == XCB_ICCCM_WM_STATE_ICONIC
const bool changedToIconic = data[0] == XCB_ICCCM_WM_STATE_ICONIC; || (data[0] == XCB_ICCCM_WM_STATE_WITHDRAWN && m_minimized));
m_minimized = changedToIconic || (changedToWithdrawn && m_minimized);
}
} }
} }
// _NET_WM_STATE handling
Qt::WindowStates newState = Qt::WindowNoState;
const NetWmStates states = netWmStates(); const NetWmStates states = netWmStates();
// _NET_WM_STATE_HIDDEN should be set by the Window Manager to indicate that a window would // _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 // 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) if ((m_windowState & Qt::WindowMinimized) && connection()->mouseGrabber() == this)
connection()->setMouseGrabber(nullptr); connection()->setMouseGrabber(nullptr);
} }
return;
} else if (event->atom == atom(QXcbAtom::_NET_FRAME_EXTENTS)) { } else if (event->atom == atom(QXcbAtom::_NET_FRAME_EXTENTS)) {
m_dirtyFrameMargins = true; m_dirtyFrameMargins = true;
} }

View File

@ -74,13 +74,12 @@ public:
Q_DECLARE_FLAGS(NetWmStates, NetWmState) Q_DECLARE_FLAGS(NetWmStates, NetWmState)
enum Task { enum RecreationReason {
Map, RecreationNotNeeded = 0,
Unmap, WindowStaysOnTopHintChanged = 0x1,
SetGeometry, WindowStaysOnBottomHintChanged = 0x2
SetWindowFlags,
SetWindowState
}; };
Q_DECLARE_FLAGS(RecreationReasons, RecreationReason)
QXcbWindow(QWindow *window); QXcbWindow(QWindow *window);
~QXcbWindow(); ~QXcbWindow();
@ -151,9 +150,6 @@ public:
QXcbWindow *toWindow() override; QXcbWindow *toWindow() override;
bool shouldDeferTask(Task task);
void handleDeferredTasks();
void handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global, void handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global,
Qt::KeyboardModifiers modifiers, QEvent::Type type, Qt::MouseEventSource source); Qt::KeyboardModifiers modifiers, QEvent::Type type, Qt::MouseEventSource source);
@ -293,10 +289,7 @@ protected:
qreal m_sizeHintsScaleFactor = 1.0; qreal m_sizeHintsScaleFactor = 1.0;
bool m_wmStateValid = true; RecreationReasons m_recreationReasons = RecreationNotNeeded;
QVector<Task> m_deferredTasks;
bool m_isWmManagedWindow = true;
QRect m_deferredGeometry;
}; };
class QXcbForeignWindow : public QXcbWindow class QXcbForeignWindow : public QXcbWindow

View File

@ -92,23 +92,39 @@ inline static QString fromSQLTCHAR(const QVarLengthArray<SQLTCHAR>& input, int s
return result; return result;
} }
template <size_t SizeOfChar = sizeof(SQLTCHAR)>
void toSQLTCHARImpl(QVarLengthArray<SQLTCHAR> &result, const QString &input); // primary template undefined
template <typename Container>
void do_append(QVarLengthArray<SQLTCHAR> &result, const Container &c)
{
result.append(reinterpret_cast<const SQLTCHAR *>(c.data()), c.size());
}
template <>
void toSQLTCHARImpl<1>(QVarLengthArray<SQLTCHAR> &result, const QString &input)
{
const auto u8 = input.toUtf8();
do_append(result, u8);
}
template <>
void toSQLTCHARImpl<2>(QVarLengthArray<SQLTCHAR> &result, const QString &input)
{
do_append(result, input);
}
template <>
void toSQLTCHARImpl<4>(QVarLengthArray<SQLTCHAR> &result, const QString &input)
{
const auto u32 = input.toUcs4();
do_append(result, u32);
}
inline static QVarLengthArray<SQLTCHAR> toSQLTCHAR(const QString &input) inline static QVarLengthArray<SQLTCHAR> toSQLTCHAR(const QString &input)
{ {
QVarLengthArray<SQLTCHAR> result; QVarLengthArray<SQLTCHAR> result;
result.resize(input.size()); toSQLTCHARImpl(result, input);
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)));
}
result.append(0); // make sure it's null terminated, doesn't matter if it already is, it does if it isn't. result.append(0); // make sure it's null terminated, doesn't matter if it already is, it does if it isn't.
return result; return result;
} }
@ -763,6 +779,14 @@ QChar QODBCDriverPrivate::quoteChar()
return quote; 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) bool QODBCDriverPrivate::setConnectionOptions(const QString& connOpts)
{ {
@ -798,10 +822,7 @@ bool QODBCDriverPrivate::setConnectionOptions(const QString& connOpts)
v = val.toUInt(); v = val.toUInt();
r = SQLSetConnectAttr(hDbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER) size_t(v), 0); r = SQLSetConnectAttr(hDbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER) size_t(v), 0);
} else if (opt.toUpper() == QLatin1String("SQL_ATTR_CURRENT_CATALOG")) { } else if (opt.toUpper() == QLatin1String("SQL_ATTR_CURRENT_CATALOG")) {
val.utf16(); // 0 terminate r = qt_string_SQLSetConnectAttr(hDbc, SQL_ATTR_CURRENT_CATALOG, val);
r = SQLSetConnectAttr(hDbc, SQL_ATTR_CURRENT_CATALOG,
toSQLTCHAR(val).data(),
val.length()*sizeof(SQLTCHAR));
} else if (opt.toUpper() == QLatin1String("SQL_ATTR_METADATA_ID")) { } else if (opt.toUpper() == QLatin1String("SQL_ATTR_METADATA_ID")) {
if (val.toUpper() == QLatin1String("SQL_TRUE")) { if (val.toUpper() == QLatin1String("SQL_TRUE")) {
v = SQL_TRUE; v = SQL_TRUE;
@ -816,10 +837,7 @@ bool QODBCDriverPrivate::setConnectionOptions(const QString& connOpts)
v = val.toUInt(); v = val.toUInt();
r = SQLSetConnectAttr(hDbc, SQL_ATTR_PACKET_SIZE, (SQLPOINTER) size_t(v), 0); r = SQLSetConnectAttr(hDbc, SQL_ATTR_PACKET_SIZE, (SQLPOINTER) size_t(v), 0);
} else if (opt.toUpper() == QLatin1String("SQL_ATTR_TRACEFILE")) { } else if (opt.toUpper() == QLatin1String("SQL_ATTR_TRACEFILE")) {
val.utf16(); // 0 terminate r = qt_string_SQLSetConnectAttr(hDbc, SQL_ATTR_TRACEFILE, val);
r = SQLSetConnectAttr(hDbc, SQL_ATTR_TRACEFILE,
toSQLTCHAR(val).data(),
val.length()*sizeof(SQLTCHAR));
} else if (opt.toUpper() == QLatin1String("SQL_ATTR_TRACE")) { } else if (opt.toUpper() == QLatin1String("SQL_ATTR_TRACE")) {
if (val.toUpper() == QLatin1String("SQL_OPT_TRACE_OFF")) { if (val.toUpper() == QLatin1String("SQL_OPT_TRACE_OFF")) {
v = SQL_OPT_TRACE_OFF; v = SQL_OPT_TRACE_OFF;
@ -1022,9 +1040,12 @@ bool QODBCResult::reset (const QString& query)
return false; return false;
} }
r = SQLExecDirect(d->hStmt, {
toSQLTCHAR(query).data(), auto encoded = toSQLTCHAR(query);
(SQLINTEGER) query.length()); r = SQLExecDirect(d->hStmt,
encoded.data(),
SQLINTEGER(encoded.size()));
}
if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO && r!= SQL_NO_DATA) { if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO && r!= SQL_NO_DATA) {
setLastError(qMakeError(QCoreApplication::translate("QODBCResult", setLastError(qMakeError(QCoreApplication::translate("QODBCResult",
"Unable to execute statement"), QSqlError::StatementError, d)); "Unable to execute statement"), QSqlError::StatementError, d));
@ -1371,9 +1392,12 @@ bool QODBCResult::prepare(const QString& query)
return false; return false;
} }
r = SQLPrepare(d->hStmt, {
toSQLTCHAR(query).data(), auto encoded = toSQLTCHAR(query);
(SQLINTEGER) query.length()); r = SQLPrepare(d->hStmt,
encoded.data(),
SQLINTEGER(encoded.size()));
}
if (r != SQL_SUCCESS) { if (r != SQL_SUCCESS) {
setLastError(qMakeError(QCoreApplication::translate("QODBCResult", setLastError(qMakeError(QCoreApplication::translate("QODBCResult",
@ -1401,7 +1425,7 @@ bool QODBCResult::exec()
SQLCloseCursor(d->hStmt); SQLCloseCursor(d->hStmt);
QVector<QVariant>& values = boundValues(); QVector<QVariant>& values = boundValues();
QVector<QByteArray> tmpStorage(values.count(), QByteArray()); // holds temporary buffers QVector<QByteArray> tmpStorage(values.count(), QByteArray()); // targets for SQLBindParameter()
QVarLengthArray<SQLLEN, 32> indicators(values.count()); QVarLengthArray<SQLLEN, 32> indicators(values.count());
memset(indicators.data(), 0, indicators.size() * sizeof(SQLLEN)); memset(indicators.data(), 0, indicators.size() * sizeof(SQLLEN));
@ -1580,35 +1604,36 @@ bool QODBCResult::exec()
case QVariant::String: case QVariant::String:
if (d->unicode) { if (d->unicode) {
QByteArray &ba = tmpStorage[i]; QByteArray &ba = tmpStorage[i];
QString str = val.toString(); {
const auto encoded = toSQLTCHAR(val.toString());
ba = QByteArray(reinterpret_cast<const char *>(encoded.data()),
encoded.size() * sizeof(SQLTCHAR));
}
if (*ind != SQL_NULL_DATA) if (*ind != SQL_NULL_DATA)
*ind = str.length() * sizeof(SQLTCHAR); *ind = ba.size();
int strSize = str.length() * sizeof(SQLTCHAR);
if (bindValueType(i) & QSql::Out) { if (bindValueType(i) & QSql::Out) {
const QVarLengthArray<SQLTCHAR> a(toSQLTCHAR(str));
ba = QByteArray((const char *)a.constData(), a.size() * sizeof(SQLTCHAR));
r = SQLBindParameter(d->hStmt, r = SQLBindParameter(d->hStmt,
i + 1, i + 1,
qParamType[bindValueType(i) & QSql::InOut], qParamType[bindValueType(i) & QSql::InOut],
SQL_C_TCHAR, SQL_C_TCHAR,
strSize > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR, ba.size() > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
0, // god knows... don't change this! 0, // god knows... don't change this!
0, 0,
ba.data(), const_cast<char *>(ba.constData()), // don't detach
ba.size(), ba.size(),
ind); ind);
break; break;
} }
ba = QByteArray ((const char *)toSQLTCHAR(str).constData(), str.size()*sizeof(SQLTCHAR));
r = SQLBindParameter(d->hStmt, r = SQLBindParameter(d->hStmt,
i + 1, i + 1,
qParamType[bindValueType(i) & QSql::InOut], qParamType[bindValueType(i) & QSql::InOut],
SQL_C_TCHAR, SQL_C_TCHAR,
strSize > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR, ba.size() > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
strSize, ba.size(),
0, 0,
const_cast<char *>(ba.constData()), const_cast<char *>(ba.constData()), // don't detach
ba.size(), ba.size(),
ind); ind);
break; break;
@ -1716,10 +1741,11 @@ bool QODBCResult::exec()
case QVariant::String: case QVariant::String:
if (d->unicode) { if (d->unicode) {
if (bindValueType(i) & QSql::Out) { if (bindValueType(i) & QSql::Out) {
const QByteArray &first = tmpStorage.at(i); const QByteArray &bytes = tmpStorage.at(i);
QVarLengthArray<SQLTCHAR> array; const auto strSize = bytes.size() / int(sizeof(SQLTCHAR));
array.append((const SQLTCHAR *)first.constData(), first.size()); QVarLengthArray<SQLTCHAR> string(strSize);
values[i] = fromSQLTCHAR(array, first.size()/sizeof(SQLTCHAR)); memcpy(string.data(), bytes.data(), strSize * sizeof(SQLTCHAR));
values[i] = fromSQLTCHAR(string);
} }
break; break;
} }
@ -1966,14 +1992,16 @@ bool QODBCDriver::open(const QString & db,
SQLSMALLINT cb; SQLSMALLINT cb;
QVarLengthArray<SQLTCHAR> connOut(1024); QVarLengthArray<SQLTCHAR> connOut(1024);
memset(connOut.data(), 0, connOut.size() * sizeof(SQLTCHAR)); memset(connOut.data(), 0, connOut.size() * sizeof(SQLTCHAR));
r = SQLDriverConnect(d->hDbc, {
NULL, auto encoded = toSQLTCHAR(connQStr);
toSQLTCHAR(connQStr).data(), r = SQLDriverConnect(d->hDbc,
(SQLSMALLINT)connQStr.length(), nullptr,
connOut.data(), encoded.data(), SQLSMALLINT(encoded.size()),
1024, connOut.data(),
&cb, 1024,
/*SQL_DRIVER_NOPROMPT*/0); &cb,
/*SQL_DRIVER_NOPROMPT*/0);
}
if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) { if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
setLastError(qMakeError(tr("Unable to connect"), QSqlError::ConnectionError, d)); setLastError(qMakeError(tr("Unable to connect"), QSqlError::ConnectionError, d));
@ -2352,17 +2380,15 @@ QStringList QODBCDriver::tables(QSql::TableType type) const
if (tableType.isEmpty()) if (tableType.isEmpty())
return tl; return tl;
QString joinedTableTypeString = tableType.join(QLatin1Char(',')); {
auto joinedTableTypeString = toSQLTCHAR(tableType.join(u','));
r = SQLTables(hStmt, r = SQLTables(hStmt,
NULL, nullptr, 0,
0, nullptr, 0,
NULL, nullptr, 0,
0, joinedTableTypeString.data(), joinedTableTypeString.size());
NULL, }
0,
toSQLTCHAR(joinedTableTypeString).data(),
joinedTableTypeString.length() /* characters, not bytes */);
if (r != SQL_SUCCESS) if (r != SQL_SUCCESS)
qSqlWarning(QLatin1String("QODBCDriver::tables Unable to execute table list"), d); 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, SQL_ATTR_CURSOR_TYPE,
(SQLPOINTER)SQL_CURSOR_FORWARD_ONLY, (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
SQL_IS_UINTEGER); SQL_IS_UINTEGER);
r = SQLPrimaryKeys(hStmt, {
catalog.length() == 0 ? NULL : toSQLTCHAR(catalog).data(), auto c = toSQLTCHAR(catalog);
catalog.length(), auto s = toSQLTCHAR(schema);
schema.length() == 0 ? NULL : toSQLTCHAR(schema).data(), auto t = toSQLTCHAR(table);
schema.length(), r = SQLPrimaryKeys(hStmt,
toSQLTCHAR(table).data(), catalog.isEmpty() ? nullptr : c.data(), c.size(),
table.length() /* in characters, not in bytes */); schema.isEmpty() ? nullptr : s.data(), s.size(),
t.data(), t.size());
}
// if the SQLPrimaryKeys() call does not succeed (e.g the driver // if the SQLPrimaryKeys() call does not succeed (e.g the driver
// does not support it) - try an alternative method to get hold of // does not support it) - try an alternative method to get hold of
// the primary index (e.g MS Access and FoxPro) // the primary index (e.g MS Access and FoxPro)
if (r != SQL_SUCCESS) { if (r != SQL_SUCCESS) {
r = SQLSpecialColumns(hStmt, auto c = toSQLTCHAR(catalog);
SQL_BEST_ROWID, auto s = toSQLTCHAR(schema);
catalog.length() == 0 ? NULL : toSQLTCHAR(catalog).data(), auto t = toSQLTCHAR(table);
catalog.length(), r = SQLSpecialColumns(hStmt,
schema.length() == 0 ? NULL : toSQLTCHAR(schema).data(), SQL_BEST_ROWID,
schema.length(), catalog.isEmpty() ? nullptr : c.data(), c.size(),
toSQLTCHAR(table).data(), schema.isEmpty() ? nullptr : s.data(), s.size(),
table.length(), t.data(), t.size(),
SQL_SCOPE_CURROW, SQL_SCOPE_CURROW,
SQL_NULLABLE); SQL_NULLABLE);
if (r != SQL_SUCCESS) { if (r != SQL_SUCCESS) {
qSqlWarning(QLatin1String("QODBCDriver::primaryIndex: Unable to execute primary key list"), d); 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, SQL_ATTR_CURSOR_TYPE,
(SQLPOINTER)SQL_CURSOR_FORWARD_ONLY, (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
SQL_IS_UINTEGER); SQL_IS_UINTEGER);
r = SQLColumns(hStmt, {
catalog.length() == 0 ? NULL : toSQLTCHAR(catalog).data(), auto c = toSQLTCHAR(catalog);
catalog.length(), auto s = toSQLTCHAR(schema);
schema.length() == 0 ? NULL : toSQLTCHAR(schema).data(), auto t = toSQLTCHAR(table);
schema.length(), r = SQLColumns(hStmt,
toSQLTCHAR(table).data(), catalog.isEmpty() ? nullptr : c.data(), c.size(),
table.length(), schema.isEmpty() ? nullptr : s.data(), s.size(),
NULL, t.data(), t.size(),
0); nullptr,
0);
}
if (r != SQL_SUCCESS) if (r != SQL_SUCCESS)
qSqlWarning(QLatin1String("QODBCDriver::record: Unable to execute column list"), d); qSqlWarning(QLatin1String("QODBCDriver::record: Unable to execute column list"), d);

View File

@ -624,6 +624,29 @@ void QMenuPrivate::hideMenu(QMenu *menu)
menu->d_func()->causedPopup.widget = nullptr; 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) void QMenuPrivate::popupAction(QAction *action, int delay, bool activateFirst)
{ {
Q_Q(QMenu); Q_Q(QMenu);
@ -3060,6 +3083,8 @@ QMenu::event(QEvent *e)
d->sloppyState.reset(); d->sloppyState.reset();
if (d->currentAction) if (d->currentAction)
d->popupAction(d->currentAction, 0, false); d->popupAction(d->currentAction, 0, false);
if (isWindow() && window() && window()->windowHandle() && !window()->windowHandle()->transientParent())
window()->windowHandle()->setTransientParent(d->transientParentWindow());
break; break;
#ifndef QT_NO_TOOLTIP #ifndef QT_NO_TOOLTIP
case QEvent::ToolTip: case QEvent::ToolTip:

View File

@ -440,6 +440,7 @@ public:
QMenuCaused causedPopup; QMenuCaused causedPopup;
void hideUpToMenuBar(); void hideUpToMenuBar();
void hideMenu(QMenu *menu); void hideMenu(QMenu *menu);
QWindow *transientParentWindow() const;
//index mappings //index mappings
inline QAction *actionAt(int i) const { return q_func()->actions().at(i); } inline QAction *actionAt(int i) const { return q_func()->actions().at(i); }

View File

@ -1498,7 +1498,7 @@ void tst_QApplication::desktopSettingsAware()
environment += QLatin1String("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM=1"); environment += QLatin1String("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM=1");
testProcess.setEnvironment(environment); testProcess.setEnvironment(environment);
#endif #endif
testProcess.start("desktopsettingsaware_helper"); testProcess.start("./desktopsettingsaware_helper");
QVERIFY2(testProcess.waitForStarted(), QVERIFY2(testProcess.waitForStarted(),
qPrintable(QString::fromLatin1("Cannot start 'desktopsettingsaware_helper': %1").arg(testProcess.errorString()))); qPrintable(QString::fromLatin1("Cannot start 'desktopsettingsaware_helper': %1").arg(testProcess.errorString())));
QVERIFY(testProcess.waitForFinished(10000)); QVERIFY(testProcess.waitForFinished(10000));
@ -2452,7 +2452,7 @@ void tst_QApplication::qtbug_12673()
#if QT_CONFIG(process) #if QT_CONFIG(process)
QProcess testProcess; QProcess testProcess;
QStringList arguments; QStringList arguments;
testProcess.start("modal_helper", arguments); testProcess.start("./modal_helper", arguments);
QVERIFY2(testProcess.waitForStarted(), QVERIFY2(testProcess.waitForStarted(),
qPrintable(QString::fromLatin1("Cannot start 'modal_helper': %1").arg(testProcess.errorString()))); qPrintable(QString::fromLatin1("Cannot start 'modal_helper': %1").arg(testProcess.errorString())));
QVERIFY(testProcess.waitForFinished(20000)); QVERIFY(testProcess.waitForFinished(20000));