summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/android/androidjniclipboard.cpp22
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp21
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.cpp5
-rw-r--r--src/plugins/platforms/android/qandroidplatformservices.cpp11
-rw-r--r--src/plugins/platforms/android/qandroidplatformtheme.cpp81
-rw-r--r--src/plugins/platforms/android/qandroidplatformtheme.h8
-rw-r--r--src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm12
-rw-r--r--src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm12
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.mm6
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm15
-rw-r--r--src/plugins/platforms/cocoa/qnsview_keys.mm9
-rw-r--r--src/plugins/platforms/cocoa/qnswindow.mm9
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp17
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h6
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp163
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen_p.h7
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice_p.h6
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm4
-rw-r--r--src/plugins/platforms/ios/qiosmessagedialog.mm20
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm2
-rw-r--r--src/plugins/platforms/ios/qiostextresponder.mm8
-rw-r--r--src/plugins/platforms/ios/quiview.mm53
-rw-r--r--src/plugins/platforms/windows/qtwindowsglobal.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp80
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp1
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp12
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp5
-rw-r--r--src/plugins/platforms/xcb/CMakeLists.txt2
-rw-r--r--src/plugins/platforms/xcb/qt_xlib_wrapper.c44
-rw-r--r--src/plugins/platforms/xcb/qt_xlib_wrapper.h54
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp8
-rw-r--r--src/plugins/platformthemes/gtk3/qgtk3theme.cpp16
-rw-r--r--src/plugins/sqldrivers/.cmake.conf2
-rw-r--r--src/plugins/sqldrivers/oci/qsql_oci_p.h2
-rw-r--r--src/plugins/sqldrivers/odbc/qsql_odbc.cpp29
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm29
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac_p_p.h3
-rw-r--r--src/plugins/styles/windowsvista/qwindowsvistastyle.cpp9
-rw-r--r--src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp16
43 files changed, 638 insertions, 188 deletions
diff --git a/src/plugins/platforms/android/androidjniclipboard.cpp b/src/plugins/platforms/android/androidjniclipboard.cpp
index 6178edd675..60f31c69da 100644
--- a/src/plugins/platforms/android/androidjniclipboard.cpp
+++ b/src/plugins/platforms/android/androidjniclipboard.cpp
@@ -71,18 +71,6 @@ namespace QtAndroidClipboard
void setClipboardMimeData(QMimeData *data)
{
clearClipboardData();
- if (data->hasText()) {
- QJniObject::callStaticMethod<void>(applicationClass(),
- "setClipboardText", "(Ljava/lang/String;)V",
- QJniObject::fromString(data->text()).object());
- }
- if (data->hasHtml()) {
- QJniObject::callStaticMethod<void>(applicationClass(),
- "setClipboardHtml",
- "(Ljava/lang/String;Ljava/lang/String;)V",
- QJniObject::fromString(data->text()).object(),
- QJniObject::fromString(data->html()).object());
- }
if (data->hasUrls()) {
QList<QUrl> urls = data->urls();
for (const auto &u : qAsConst(urls)) {
@@ -91,6 +79,16 @@ namespace QtAndroidClipboard
"(Ljava/lang/String;)V",
QJniObject::fromString(u.toEncoded()).object());
}
+ } else if (data->hasText()) { // hasText || hasUrls, so the order matter here.
+ QJniObject::callStaticMethod<void>(applicationClass(),
+ "setClipboardText", "(Ljava/lang/String;)V",
+ QJniObject::fromString(data->text()).object());
+ } else if (data->hasHtml()) {
+ QJniObject::callStaticMethod<void>(applicationClass(),
+ "setClipboardHtml",
+ "(Ljava/lang/String;Ljava/lang/String;)V",
+ QJniObject::fromString(data->text()).object(),
+ QJniObject::fromString(data->html()).object());
}
}
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index 8136ecd769..6b8b30c310 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -667,24 +667,27 @@ static void setDisplayMetrics(JNIEnv * /*env*/, jclass /*clazz*/, jint screenWid
jint availableHeightPixels, jdouble xdpi, jdouble ydpi,
jdouble scaledDensity, jdouble density, jfloat refreshRate)
{
+ Q_UNUSED(availableLeftPixels)
+ Q_UNUSED(availableTopPixels)
+
m_availableWidthPixels = availableWidthPixels;
m_availableHeightPixels = availableHeightPixels;
m_scaledDensity = scaledDensity;
m_density = density;
+ const QSize screenSize(screenWidthPixels, screenHeightPixels);
+ // available geometry always starts from top left
+ const QRect availableGeometry(0, 0, availableWidthPixels, availableHeightPixels);
+ const QSize physicalSize(qRound(double(screenWidthPixels) / xdpi * 25.4),
+ qRound(double(screenHeightPixels) / ydpi * 25.4));
+
QMutexLocker lock(&m_platformMutex);
if (!m_androidPlatformIntegration) {
QAndroidPlatformIntegration::setDefaultDisplayMetrics(
- availableLeftPixels, availableTopPixels, availableWidthPixels,
- availableHeightPixels, qRound(double(screenWidthPixels) / xdpi * 25.4),
- qRound(double(screenHeightPixels) / ydpi * 25.4), screenWidthPixels,
- screenHeightPixels);
+ availableGeometry.left(), availableGeometry.top(), availableGeometry.width(),
+ availableGeometry.height(), physicalSize.width(), physicalSize.height(),
+ screenSize.width(), screenSize.height());
} else {
- const QSize physicalSize(qRound(double(screenWidthPixels) / xdpi * 25.4),
- qRound(double(screenHeightPixels) / ydpi * 25.4));
- const QSize screenSize(screenWidthPixels, screenHeightPixels);
- const QRect availableGeometry(availableLeftPixels, availableTopPixels,
- availableWidthPixels, availableHeightPixels);
m_androidPlatformIntegration->setScreenSizeParameters(physicalSize, screenSize,
availableGeometry);
m_androidPlatformIntegration->setRefreshRate(refreshRate);
diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp
index 24111fc611..9568801bcf 100644
--- a/src/plugins/platforms/android/qandroidplatformintegration.cpp
+++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp
@@ -466,7 +466,7 @@ QStringList QAndroidPlatformIntegration::themeNames() const
QPlatformTheme *QAndroidPlatformIntegration::createPlatformTheme(const QString &name) const
{
if (androidThemeName == name)
- return new QAndroidPlatformTheme(m_androidPlatformNativeInterface);
+ return QAndroidPlatformTheme::instance(m_androidPlatformNativeInterface);
return 0;
}
@@ -529,6 +529,9 @@ void QAndroidPlatformIntegration::setAppearance(QPlatformTheme::Appearance newAp
if (m_appearance == newAppearance)
return;
m_appearance = newAppearance;
+
+ QMetaObject::invokeMethod(qGuiApp,
+ [] () { QAndroidPlatformTheme::instance()->updateAppearance();});
}
void QAndroidPlatformIntegration::setScreenSizeParameters(const QSize &physicalSize,
diff --git a/src/plugins/platforms/android/qandroidplatformservices.cpp b/src/plugins/platforms/android/qandroidplatformservices.cpp
index 8c2af5fff4..30af140837 100644
--- a/src/plugins/platforms/android/qandroidplatformservices.cpp
+++ b/src/plugins/platforms/android/qandroidplatformservices.cpp
@@ -81,12 +81,13 @@ bool QAndroidPlatformServices::openUrl(const QUrl &theUrl)
// if the file is local, we need to pass the MIME type, otherwise Android
// does not start an Intent to view this file
QLatin1String fileScheme("file");
- if ((url.scheme().isEmpty() || url.scheme() == fileScheme) && QFile::exists(url.path())) {
- // a real URL including the scheme is needed, else the Intent can not be started
+
+ // a real URL including the scheme is needed, else the Intent can not be started
+ if (url.scheme().isEmpty())
url.setScheme(fileScheme);
- QMimeDatabase mimeDb;
- mime = mimeDb.mimeTypeForUrl(url).name();
- }
+
+ if (url.scheme() == fileScheme)
+ mime = QMimeDatabase().mimeTypeForUrl(url).name();
using namespace QNativeInterface;
QJniObject urlString = QJniObject::fromString(url.toString());
diff --git a/src/plugins/platforms/android/qandroidplatformtheme.cpp b/src/plugins/platforms/android/qandroidplatformtheme.cpp
index e51d6a099c..4958800954 100644
--- a/src/plugins/platforms/android/qandroidplatformtheme.cpp
+++ b/src/plugins/platforms/android/qandroidplatformtheme.cpp
@@ -192,6 +192,9 @@ QJsonObject AndroidStyle::loadStyleData()
if (!stylePath.isEmpty() && !stylePath.endsWith(slashChar))
stylePath += slashChar;
+ if (QAndroidPlatformIntegration::appearance() == QPlatformTheme::Appearance::Dark)
+ stylePath += QLatin1String("darkUiMode/");
+
Q_ASSERT(!stylePath.isEmpty());
QString androidTheme = QLatin1String(qgetenv("QT_ANDROID_THEME"));
@@ -219,13 +222,22 @@ QJsonObject AndroidStyle::loadStyleData()
return document.object();
}
-static std::shared_ptr<AndroidStyle> loadAndroidStyle(QPalette *defaultPalette)
+static void loadAndroidStyle(QPalette *defaultPalette, std::shared_ptr<AndroidStyle> &style)
{
double pixelDensity = QHighDpiScaling::isActive() ? QtAndroid::pixelDensity() : 1.0;
- std::shared_ptr<AndroidStyle> style = std::make_shared<AndroidStyle>();
+ if (style) {
+ style->m_standardPalette = QPalette();
+ style->m_palettes.clear();
+ style->m_fonts.clear();
+ style->m_QWidgetsFonts.clear();
+ } else {
+ style = std::make_shared<AndroidStyle>();
+ }
+
style->m_styleData = AndroidStyle::loadStyleData();
+
if (style->m_styleData.isEmpty())
- return std::shared_ptr<AndroidStyle>();
+ return;
{
QFont font(QLatin1String("Droid Sans Mono"), 14.0 * 100 / 72);
@@ -327,11 +339,44 @@ static std::shared_ptr<AndroidStyle> loadAndroidStyle(QPalette *defaultPalette)
// Extract palette information
}
}
- return style;
+}
+
+QAndroidPlatformTheme *QAndroidPlatformTheme::m_instance = nullptr;
+
+QAndroidPlatformTheme *QAndroidPlatformTheme::instance(
+ QAndroidPlatformNativeInterface *androidPlatformNativeInterface)
+{
+ if (androidPlatformNativeInterface && !m_instance) {
+ m_instance = new QAndroidPlatformTheme(androidPlatformNativeInterface);
+ }
+ return m_instance;
}
QAndroidPlatformTheme::QAndroidPlatformTheme(QAndroidPlatformNativeInterface *androidPlatformNativeInterface)
{
+ updateStyle();
+
+ androidPlatformNativeInterface->m_androidStyle = m_androidStyleData;
+
+ // default in case the style has not set a font
+ m_systemFont = QFont(QLatin1String("Roboto"), 14.0 * 100 / 72);
+}
+
+QAndroidPlatformTheme::~QAndroidPlatformTheme()
+{
+ m_instance = nullptr;
+}
+
+void QAndroidPlatformTheme::updateAppearance()
+{
+ updateStyle();
+ for (QWindow *w : QGuiApplication::allWindows())
+ QWindowSystemInterface::handleThemeChange(w);
+}
+
+void QAndroidPlatformTheme::updateStyle()
+{
+ QColor windowText = Qt::black;
QColor background(229, 229, 229);
QColor light = background.lighter(150);
QColor mid(background.darker(130));
@@ -348,7 +393,27 @@ QAndroidPlatformTheme::QAndroidPlatformTheme(QAndroidPlatformNativeInterface *an
QColor highlight(148, 210, 231);
QColor disabledShadow = shadow.lighter(150);
- m_defaultPalette = QPalette(Qt::black,background,light,dark,mid,text,base);
+ if (appearance() == QPlatformTheme::Appearance::Dark) {
+ // Colors were prepared based on Theme.DeviceDefault.DayNight
+ windowText = QColor(250, 250, 250);
+ background = QColor(48, 48, 48);
+ light = background.darker(150);
+ mid = background.lighter(130);
+ midLight = mid.darker(110);
+ base = background;
+ disabledBase = background;
+ dark = background.darker(150);
+ darkDisabled = dark.darker(110);
+ text = QColor(250, 250, 250);
+ highlightedText = QColor(250, 250, 250);
+ disabledText = QColor(96, 96, 96);
+ button = QColor(48, 48, 48);
+ shadow = QColor(32, 32, 32);
+ highlight = QColor(102, 178, 204);
+ disabledShadow = shadow.darker(150);
+ }
+
+ m_defaultPalette = QPalette(windowText,background,light,dark,mid,text,base);
m_defaultPalette.setBrush(QPalette::Midlight, midLight);
m_defaultPalette.setBrush(QPalette::Button, button);
m_defaultPalette.setBrush(QPalette::Shadow, shadow);
@@ -364,12 +429,8 @@ QAndroidPlatformTheme::QAndroidPlatformTheme(QAndroidPlatformNativeInterface *an
m_defaultPalette.setBrush(QPalette::Active, QPalette::Highlight, highlight);
m_defaultPalette.setBrush(QPalette::Inactive, QPalette::Highlight, highlight);
m_defaultPalette.setBrush(QPalette::Disabled, QPalette::Highlight, highlight.lighter(150));
- m_androidStyleData = loadAndroidStyle(&m_defaultPalette);
- QGuiApplication::setPalette(m_defaultPalette);
- androidPlatformNativeInterface->m_androidStyle = m_androidStyleData;
- // default in case the style has not set a font
- m_systemFont = QFont(QLatin1String("Roboto"), 14.0 * 100 / 72); // keep default size the same after changing from 100 dpi to 72 dpi
+ loadAndroidStyle(&m_defaultPalette, m_androidStyleData);
}
QPlatformMenuBar *QAndroidPlatformTheme::createPlatformMenuBar() const
diff --git a/src/plugins/platforms/android/qandroidplatformtheme.h b/src/plugins/platforms/android/qandroidplatformtheme.h
index 6084631e3d..5dda790cca 100644
--- a/src/plugins/platforms/android/qandroidplatformtheme.h
+++ b/src/plugins/platforms/android/qandroidplatformtheme.h
@@ -64,7 +64,9 @@ class QAndroidPlatformNativeInterface;
class QAndroidPlatformTheme: public QPlatformTheme
{
public:
- QAndroidPlatformTheme(QAndroidPlatformNativeInterface * androidPlatformNativeInterface);
+ ~QAndroidPlatformTheme();
+ void updateAppearance();
+ void updateStyle();
QPlatformMenuBar *createPlatformMenuBar() const override;
QPlatformMenu *createPlatformMenu() const override;
QPlatformMenuItem *createPlatformMenuItem() const override;
@@ -77,8 +79,12 @@ public:
bool usePlatformNativeDialog(DialogType type) const override;
QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const override;
+ static QAndroidPlatformTheme *instance(
+ QAndroidPlatformNativeInterface * androidPlatformNativeInterface = nullptr);
private:
+ QAndroidPlatformTheme(QAndroidPlatformNativeInterface * androidPlatformNativeInterface);
+ static QAndroidPlatformTheme * m_instance;
std::shared_ptr<AndroidStyle> m_androidStyleData;
QPalette m_defaultPalette;
QFont m_systemFont;
diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
index b21b7c2cc9..46526088fe 100644
--- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
@@ -218,7 +218,17 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate);
mDialogIsExecuting = false;
mResultSet = false;
mClosingDueToKnownButton = false;
- [mColorPanel makeKeyAndOrderFront:mColorPanel];
+ // Make this an asynchronous call, so the panel is made key only
+ // in the next event loop run. This is to make sure that by
+ // the time the modal loop is run in runModalForWindow below,
+ // which internally also sets the panel to key window,
+ // the panel is not yet key, and the NSApp still has the right
+ // reference to the _previousKeyWindow. Otherwise both NSApp.key
+ // and NSApp._previousKeyWindow would wrongly point to the panel,
+ // loosing any reference to the window that was key before.
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [mColorPanel makeKeyAndOrderFront:mColorPanel];
+ });
}
- (BOOL)runApplicationModalPanel
diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
index 355d658242..91f24e2d5f 100644
--- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
@@ -202,7 +202,17 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
{
mDialogIsExecuting = false;
mResultSet = false;
- [mFontPanel makeKeyAndOrderFront:mFontPanel];
+ // Make this an asynchronous call, so the panel is made key only
+ // in the next event loop run. This is to make sure that by
+ // the time the modal loop is run in runModalForWindow below,
+ // which internally also sets the panel to key window,
+ // the panel is not yet key, and the NSApp still has the right
+ // reference to the _previousKeyWindow. Otherwise both NSApp.key
+ // and NSApp._previousKeyWindow would wrongly point to the panel,
+ // loosing any reference to the window that was key before.
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [mFontPanel makeKeyAndOrderFront:mFontPanel];
+ });
}
- (BOOL)runApplicationModalPanel
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h
index 7a3ab5fd6f..548692a5bb 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.h
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.h
@@ -349,7 +349,7 @@ QSendSuperHelper<Args...> qt_objcDynamicSuperHelper(id receiver, SEL selector, A
// -------------------------------------------------------------------------
-struct InputMethodQueryResult : public QHash<Qt::InputMethodQuery, QVariant>
+struct InputMethodQueryResult : public QHash<int, QVariant>
{
operator bool() { return !isEmpty(); }
};
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm
index a6804accde..7a925081a7 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.mm
+++ b/src/plugins/platforms/cocoa/qcocoatheme.mm
@@ -486,6 +486,12 @@ QVariant QCocoaTheme::themeHint(ThemeHint hint) const
return QVariant(bool([[NSApplication sharedApplication] presentationOptions] & NSApplicationPresentationFullScreen));
case QPlatformTheme::InteractiveResizeAcrossScreens:
return !NSScreen.screensHaveSeparateSpaces;
+ case QPlatformTheme::MouseDoubleClickInterval:
+ return NSEvent.doubleClickInterval * 1000;
+ case QPlatformTheme::KeyboardInputInterval:
+ return NSEvent.keyRepeatDelay * 1000;
+ case QPlatformTheme::KeyboardAutoRepeatRate:
+ return 1.0 / NSEvent.keyRepeatInterval;
default:
break;
}
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 8077c6707c..bf6fa90e88 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -731,9 +731,10 @@ void QCocoaWindow::applyWindowState(Qt::WindowStates requestedState)
switch (currentState) {
case Qt::WindowMinimized:
[nsWindow deminiaturize:sender];
- Q_ASSERT_X(windowState() != Qt::WindowMinimized, "QCocoaWindow",
- "[NSWindow deminiaturize:] is synchronous");
- break;
+ // Deminiaturizing is not synchronous, so we need to wait for the
+ // NSWindowDidMiniaturizeNotification before continuing to apply
+ // the new state.
+ return;
case Qt::WindowFullScreen: {
toggleFullScreen();
// Exiting fullscreen is not synchronous, so we need to wait for the
@@ -904,7 +905,15 @@ void QCocoaWindow::windowDidDeminiaturize()
if (!isContentView())
return;
+ Qt::WindowState requestedState = window()->windowState();
+
handleWindowStateChanged();
+
+ if (requestedState != windowState() && requestedState != Qt::WindowMinimized) {
+ // We were only going out of minimized as an intermediate step before
+ // progressing into the final step, so re-sync the desired state.
+ applyWindowState(requestedState);
+ }
}
void QCocoaWindow::handleWindowStateChanged(HandleFlags flags)
diff --git a/src/plugins/platforms/cocoa/qnsview_keys.mm b/src/plugins/platforms/cocoa/qnsview_keys.mm
index 307d846b1d..62e64b0cef 100644
--- a/src/plugins/platforms/cocoa/qnsview_keys.mm
+++ b/src/plugins/platforms/cocoa/qnsview_keys.mm
@@ -249,9 +249,16 @@ KeyEvent::KeyEvent(NSEvent *nsevent)
default: break; // Must be manually set
}
- if (nsevent.type == NSEventTypeKeyDown || nsevent.type == NSEventTypeKeyUp) {
+ switch (nsevent.type) {
+ case NSEventTypeKeyDown:
+ case NSEventTypeKeyUp:
+ case NSEventTypeFlagsChanged:
nativeVirtualKey = nsevent.keyCode;
+ default:
+ break;
+ }
+ if (nsevent.type == NSEventTypeKeyDown || nsevent.type == NSEventTypeKeyUp) {
NSString *charactersIgnoringModifiers = nsevent.charactersIgnoringModifiers;
NSString *characters = nsevent.characters;
diff --git a/src/plugins/platforms/cocoa/qnswindow.mm b/src/plugins/platforms/cocoa/qnswindow.mm
index 228773d8ec..a35f8cf22a 100644
--- a/src/plugins/platforms/cocoa/qnswindow.mm
+++ b/src/plugins/platforms/cocoa/qnswindow.mm
@@ -328,8 +328,13 @@ OSStatus CGSClearWindowTags(const CGSConnectionID, const CGSWindowID, int *, int
// we assume that if you have translucent content, without a
// frame then you intend to do all background drawing yourself.
const QWindow *window = m_platformWindow ? m_platformWindow->window() : nullptr;
- if (!self.opaque && window && window->flags().testFlag(Qt::FramelessWindowHint))
- return [NSColor clearColor];
+ if (!self.opaque && window) {
+ // Qt::Popup also requires clearColor - in qmacstyle
+ // we fill background using a special path with rounded corners.
+ if (window->flags().testFlag(Qt::FramelessWindowHint)
+ || (window->flags() & Qt::WindowType_Mask) == Qt::Popup)
+ return [NSColor clearColor];
+ }
// This still allows you to have translucent content with a frame,
// where the system background (or color set via NSWindow) will
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
index b5b7811b79..a98ed0b812 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
@@ -83,7 +83,13 @@ bool QEglFSKmsGbmDevice::open()
setFd(fd);
- m_eventReader.create(this);
+ if (usesEventReader()) {
+ qCDebug(qLcEglfsKmsDebug, "Using dedicated drm event reading thread");
+ m_eventReader.create(this);
+ } else {
+ qCDebug(qLcEglfsKmsDebug, "Not using dedicated drm event reading thread; "
+ "threaded multi-screen setups may experience problems");
+ }
return true;
}
@@ -92,7 +98,8 @@ void QEglFSKmsGbmDevice::close()
{
// Note: screens are gone at this stage.
- m_eventReader.destroy();
+ if (usesEventReader())
+ m_eventReader.destroy();
if (m_gbm_device) {
gbm_device_destroy(m_gbm_device);
@@ -174,4 +181,10 @@ void QEglFSKmsGbmDevice::registerScreen(QPlatformScreen *screen,
m_globalCursor->reevaluateVisibilityForScreens();
}
+bool QEglFSKmsGbmDevice::usesEventReader() const
+{
+ static const bool eventReaderThreadDisabled = qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_NO_EVENT_READER_THREAD");
+ return !eventReaderThreadDisabled;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h
index bb67d800ee..d7bd1f613c 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h
@@ -55,6 +55,7 @@
#include "qeglfskmsgbmcursor_p.h"
#include <private/qeglfskmsdevice_p.h>
+#include <private/qeglfskmseventreader_p.h>
#include <gbm.h>
@@ -87,11 +88,14 @@ public:
const QPoint &virtualPos,
const QList<QPlatformScreen *> &virtualSiblings) override;
+ bool usesEventReader() const;
+ QEglFSKmsEventReader *eventReader() { return &m_eventReader; }
+
private:
Q_DISABLE_COPY(QEglFSKmsGbmDevice)
gbm_device *m_gbm_device;
-
+ QEglFSKmsEventReader m_eventReader;
QEglFSKmsGbmCursor *m_globalCursor;
};
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
index 301aaf15bf..ba9b35f36f 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
@@ -56,6 +56,8 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
+QMutex QEglFSKmsGbmScreen::m_nonThreadedFlipMutex;
+
static inline uint32_t drmFormatToGbmFormat(uint32_t drmFormat)
{
Q_ASSERT(DRM_FORMAT_XRGB8888 == GBM_FORMAT_XRGB8888);
@@ -207,8 +209,10 @@ void QEglFSKmsGbmScreen::initCloning(QPlatformScreen *screenThisScreenClones,
qWarning("QEglFSKmsGbmScreen %s cannot be clone source and destination at the same time", qPrintable(name()));
return;
}
- if (clonesAnother)
+ if (clonesAnother) {
m_cloneSource = static_cast<QEglFSKmsGbmScreen *>(screenThisScreenClones);
+ qCDebug(qLcEglfsKmsDebug, "Screen %s clones %s", qPrintable(name()), qPrintable(m_cloneSource->name()));
+ }
// clone sources need to know their additional destinations
for (QPlatformScreen *s : screensCloningThisScreen) {
@@ -263,6 +267,31 @@ void QEglFSKmsGbmScreen::ensureModeSet(uint32_t fb)
}
}
+void QEglFSKmsGbmScreen::nonThreadedPageFlipHandler(int fd,
+ unsigned int sequence,
+ unsigned int tv_sec,
+ unsigned int tv_usec,
+ void *user_data)
+{
+ // note that with cloning involved this callback is called also for screens that clone another one
+ Q_UNUSED(fd);
+ Q_UNUSED(sequence);
+ Q_UNUSED(tv_sec);
+ Q_UNUSED(tv_usec);
+ QEglFSKmsGbmScreen *screen = static_cast<QEglFSKmsGbmScreen *>(user_data);
+ screen->flipFinished();
+}
+
+void QEglFSKmsGbmScreen::waitForFlipWithEventReader(QEglFSKmsGbmScreen *screen)
+{
+ m_flipMutex.lock();
+ QEglFSKmsGbmDevice *dev = static_cast<QEglFSKmsGbmDevice *>(device());
+ dev->eventReader()->startWaitFlip(screen, &m_flipMutex, &m_flipCond);
+ m_flipCond.wait(&m_flipMutex);
+ m_flipMutex.unlock();
+ screen->flipFinished();
+}
+
void QEglFSKmsGbmScreen::waitForFlip()
{
if (m_headless || m_cloneSource)
@@ -272,18 +301,69 @@ void QEglFSKmsGbmScreen::waitForFlip()
if (!m_gbm_bo_next)
return;
- m_flipMutex.lock();
- device()->eventReader()->startWaitFlip(this, &m_flipMutex, &m_flipCond);
- m_flipCond.wait(&m_flipMutex);
- m_flipMutex.unlock();
-
- flipFinished();
+ QEglFSKmsGbmDevice *dev = static_cast<QEglFSKmsGbmDevice *>(device());
+ if (dev->usesEventReader()) {
+ waitForFlipWithEventReader(this);
+ // Now, unlike on the other code path, we need to ensure the
+ // flips have completed for the screens that just scan out
+ // this one's content, because the eventReader's wait is
+ // per-output.
+ for (CloneDestination &d : m_cloneDests) {
+ if (d.screen != this)
+ waitForFlipWithEventReader(d.screen);
+ }
+ } else {
+ QMutexLocker lock(&m_nonThreadedFlipMutex);
+ while (m_gbm_bo_next) {
+ drmEventContext drmEvent;
+ memset(&drmEvent, 0, sizeof(drmEvent));
+ drmEvent.version = 2;
+ drmEvent.vblank_handler = nullptr;
+ drmEvent.page_flip_handler = nonThreadedPageFlipHandler;
+ drmHandleEvent(device()->fd(), &drmEvent);
+ }
+ }
#if QT_CONFIG(drm_atomic)
device()->threadLocalAtomicReset();
#endif
}
+#if QT_CONFIG(drm_atomic)
+static void addAtomicFlip(drmModeAtomicReq *request, const QKmsOutput &output, uint32_t fb)
+{
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->framebufferPropertyId, fb);
+
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->crtcPropertyId, output.crtc_id);
+
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->srcwidthPropertyId, output.size.width() << 16);
+
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->srcXPropertyId, 0);
+
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->srcYPropertyId, 0);
+
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->srcheightPropertyId, output.size.height() << 16);
+
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->crtcXPropertyId, 0);
+
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->crtcYPropertyId, 0);
+
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->crtcwidthPropertyId, output.modes[output.mode].hdisplay);
+
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->crtcheightPropertyId, output.modes[output.mode].vdisplay);
+}
+#endif
+
void QEglFSKmsGbmScreen::flip()
{
// For headless screen just return silently. It is not necessarily an error
@@ -303,14 +383,14 @@ void QEglFSKmsGbmScreen::flip()
m_gbm_bo_next = gbm_surface_lock_front_buffer(m_gbm_surface);
if (!m_gbm_bo_next) {
- qWarning("Could not lock GBM surface front buffer!");
+ qWarning("Could not lock GBM surface front buffer for screen %s", qPrintable(name()));
return;
}
FrameBuffer *fb = framebufferForBufferObject(m_gbm_bo_next);
ensureModeSet(fb->fb);
- QKmsOutput &op(output());
+ const QKmsOutput &thisOutput(output());
const int fd = device()->fd();
m_flipPending = true;
@@ -318,35 +398,25 @@ void QEglFSKmsGbmScreen::flip()
#if QT_CONFIG(drm_atomic)
drmModeAtomicReq *request = device()->threadLocalAtomicRequest();
if (request) {
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->framebufferPropertyId, fb->fb);
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcPropertyId, op.crtc_id);
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcwidthPropertyId,
- op.size.width() << 16);
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcXPropertyId, 0);
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcYPropertyId, 0);
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcheightPropertyId,
- op.size.height() << 16);
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcXPropertyId, 0);
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcYPropertyId, 0);
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcwidthPropertyId,
- m_output.modes[m_output.mode].hdisplay);
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcheightPropertyId,
- m_output.modes[m_output.mode].vdisplay);
-
+ addAtomicFlip(request, thisOutput, fb->fb);
static int zpos = qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_ZPOS");
- if (zpos)
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->zposPropertyId, zpos);
+ if (zpos) {
+ drmModeAtomicAddProperty(request, thisOutput.eglfs_plane->id,
+ thisOutput.eglfs_plane->zposPropertyId, zpos);
+ }
static uint blendOp = uint(qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_BLEND_OP"));
- if (blendOp)
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->blendOpPropertyId, blendOp);
+ if (blendOp) {
+ drmModeAtomicAddProperty(request, thisOutput.eglfs_plane->id,
+ thisOutput.eglfs_plane->blendOpPropertyId, blendOp);
+ }
}
#endif
} else {
int ret = drmModePageFlip(fd,
- op.crtc_id,
- fb->fb,
- DRM_MODE_PAGE_FLIP_EVENT,
- this);
+ thisOutput.crtc_id,
+ fb->fb,
+ DRM_MODE_PAGE_FLIP_EVENT,
+ this);
if (ret) {
qErrnoWarning("Could not queue DRM page flip on screen %s", qPrintable(name()));
m_flipPending = false;
@@ -360,17 +430,20 @@ void QEglFSKmsGbmScreen::flip()
if (d.screen != this) {
d.screen->ensureModeSet(fb->fb);
d.cloneFlipPending = true;
- QKmsOutput &destOutput(d.screen->output());
+ const QKmsOutput &destOutput(d.screen->output());
if (device()->hasAtomicSupport()) {
#if QT_CONFIG(drm_atomic)
drmModeAtomicReq *request = device()->threadLocalAtomicRequest();
- if (request) {
- drmModeAtomicAddProperty(request, destOutput.eglfs_plane->id,
- destOutput.eglfs_plane->framebufferPropertyId, fb->fb);
- drmModeAtomicAddProperty(request, destOutput.eglfs_plane->id,
- destOutput.eglfs_plane->crtcPropertyId, destOutput.crtc_id);
- }
+ if (request)
+ addAtomicFlip(request, destOutput, fb->fb);
+
+ // ### This path is broken. On the other branch we can easily
+ // pass in d.screen as the user_data for drmModePageFlip, but
+ // using one atomic request breaks down here since we get events
+ // with the same user_data passed to drmModeAtomicCommit. Until
+ // this gets reworked (multiple requests?) screen cloning is not
+ // compatible with atomic.
#endif
} else {
int ret = drmModePageFlip(fd,
@@ -379,7 +452,9 @@ void QEglFSKmsGbmScreen::flip()
DRM_MODE_PAGE_FLIP_EVENT,
d.screen);
if (ret) {
- qErrnoWarning("Could not queue DRM page flip for clone screen %s", qPrintable(name()));
+ qErrnoWarning("Could not queue DRM page flip for screen %s (clones screen %s)",
+ qPrintable(d.screen->name()),
+ qPrintable(name()));
d.cloneFlipPending = false;
}
}
@@ -415,8 +490,11 @@ void QEglFSKmsGbmScreen::cloneDestFlipFinished(QEglFSKmsGbmScreen *cloneDestScre
void QEglFSKmsGbmScreen::updateFlipStatus()
{
- Q_ASSERT(!m_cloneSource);
+ // only for 'real' outputs that own the color buffer, i.e. that are not cloning another one
+ if (m_cloneSource)
+ return;
+ // proceed only if flips for both this and all others that clone this have finished
if (m_flipPending)
return;
@@ -425,9 +503,10 @@ void QEglFSKmsGbmScreen::updateFlipStatus()
return;
}
- if (m_gbm_bo_current)
+ if (m_gbm_bo_current) {
gbm_surface_release_buffer(m_gbm_surface,
m_gbm_bo_current);
+ }
m_gbm_bo_current = m_gbm_bo_next;
m_gbm_bo_next = nullptr;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen_p.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen_p.h
index ae12e95e62..d7cf0a28be 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen_p.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen_p.h
@@ -88,6 +88,12 @@ protected:
void flipFinished();
void ensureModeSet(uint32_t fb);
void cloneDestFlipFinished(QEglFSKmsGbmScreen *cloneDestScreen);
+ void waitForFlipWithEventReader(QEglFSKmsGbmScreen *screen);
+ static void nonThreadedPageFlipHandler(int fd,
+ unsigned int sequence,
+ unsigned int tv_sec,
+ unsigned int tv_usec,
+ void *user_data);
gbm_surface *m_gbm_surface;
@@ -97,6 +103,7 @@ protected:
QMutex m_flipMutex;
QWaitCondition m_flipCond;
+ static QMutex m_nonThreadedFlipMutex;
QScopedPointer<QEglFSKmsGbmCursor> m_cursor;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice_p.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice_p.h
index 006f4a656e..0a7679f765 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice_p.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice_p.h
@@ -53,7 +53,6 @@
//
#include "private/qeglfsglobal_p.h"
-#include "qeglfskmseventreader_p.h"
#include <QtKmsSupport/private/qkmsdevice_p.h>
QT_BEGIN_NAMESPACE
@@ -67,11 +66,6 @@ public:
bool isPrimary,
const QPoint &virtualPos,
const QList<QPlatformScreen *> &virtualSiblings) override;
-
- QEglFSKmsEventReader *eventReader() { return &m_eventReader; }
-
-protected:
- QEglFSKmsEventReader m_eventReader;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index af09704a21..de6b724742 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -160,7 +160,7 @@ static QUIView *focusView()
return;
// Enable hide-keyboard gesture
- self.enabled = YES;
+ self.enabled = m_context->isInputPanelVisible();
m_context->scrollToCursor();
}
@@ -402,7 +402,7 @@ void QIOSInputContext::updateKeyboardState(NSNotification *notification)
// The isInputPanelVisible() property is based on whether or not the virtual keyboard
// is visible on screen, and does not follow the logic of the iOS WillShow and WillHide
// notifications which are not emitted for undocked keyboards, and are buggy when dealing
- // with input-accesosory-views. The reason for using frameEnd here (the future state),
+ // with input-accessory-views. The reason for using frameEnd here (the future state),
// instead of the current state reflected in frameBegin, is that QInputMethod::isVisible()
// is documented to reflect the future state in the case of animated transitions.
m_keyboardState.keyboardVisible = CGRectIntersectsRect(frameEnd, [UIScreen mainScreen].bounds);
diff --git a/src/plugins/platforms/ios/qiosmessagedialog.mm b/src/plugins/platforms/ios/qiosmessagedialog.mm
index 254922701a..773b034e2a 100644
--- a/src/plugins/platforms/ios/qiosmessagedialog.mm
+++ b/src/plugins/platforms/ios/qiosmessagedialog.mm
@@ -47,6 +47,7 @@
#include "qiosglobal.h"
#include "quiview.h"
+#include "qiosscreen.h"
#include "qiosmessagedialog.h"
QIOSMessageDialog::QIOSMessageDialog()
@@ -147,6 +148,25 @@ bool QIOSMessageDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality win
}
UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window : qt_apple_sharedApplication().keyWindow;
+ if (!window) {
+ qCDebug(lcQpaWindow, "Attempting to exec a dialog without any window/widget visible.");
+
+ auto *primaryScreen = static_cast<QIOSScreen*>(QGuiApplication::primaryScreen()->handle());
+ Q_ASSERT(primaryScreen);
+
+ window = primaryScreen->uiWindow();
+ if (window.hidden) {
+ // With a window hidden, an attempt to present view controller
+ // below fails with a warning, that a view "is not a part of
+ // any view hierarchy". The UIWindow is initially hidden,
+ // as unhiding it is what hides the splash screen.
+ window.hidden = NO;
+ }
+ }
+
+ if (!window)
+ return false;
+
[window.rootViewController presentViewController:m_alertController animated:YES completion:nil];
return true;
}
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm
index 4c79dcc34c..915fc4791f 100644
--- a/src/plugins/platforms/ios/qiosscreen.mm
+++ b/src/plugins/platforms/ios/qiosscreen.mm
@@ -288,7 +288,7 @@ QIOSScreen::QIOSScreen(UIScreen *screen)
if (!qt_apple_isApplicationExtension()) {
for (UIWindow *existingWindow in qt_apple_sharedApplication().windows) {
if (existingWindow.screen == m_uiScreen) {
- m_uiWindow = [m_uiWindow retain];
+ m_uiWindow = [existingWindow retain];
break;
}
}
diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm
index a65f8bbaa1..30ce9b8a83 100644
--- a/src/plugins/platforms/ios/qiostextresponder.mm
+++ b/src/plugins/platforms/ios/qiostextresponder.mm
@@ -889,20 +889,20 @@
[self sendEventToFocusObject:e];
}
-- (void)setBaseWritingDirection:(UITextWritingDirection)writingDirection forRange:(UITextRange *)range
+- (void)setBaseWritingDirection:(NSWritingDirection)writingDirection forRange:(UITextRange *)range
{
Q_UNUSED(writingDirection);
Q_UNUSED(range);
// Writing direction is handled by QLocale
}
-- (UITextWritingDirection)baseWritingDirectionForPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction
+- (NSWritingDirection)baseWritingDirectionForPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction
{
Q_UNUSED(position);
Q_UNUSED(direction);
if (QLocale::system().textDirection() == Qt::RightToLeft)
- return UITextWritingDirectionRightToLeft;
- return UITextWritingDirectionLeftToRight;
+ return NSWritingDirectionRightToLeft;
+ return NSWritingDirectionLeftToRight;
}
- (UITextRange *)characterRangeByExtendingPosition:(UITextPosition *)position inDirection:(UITextLayoutDirection)direction
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index 4f3ed7dadf..c5e80e0a32 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -630,13 +630,33 @@ inline ulong getTimeStamp(UIEvent *event)
return Qt::Key_unknown;
}
-- (bool)processPresses:(NSSet *)presses withType:(QEvent::Type)type {
+- (bool)isControlKey:(Qt::Key)key
+{
+ switch (key) {
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ case Qt::Key_Left:
+ case Qt::Key_Right:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+- (bool)handlePresses:(NSSet<UIPress *> *)presses eventType:(QEvent::Type)type
+{
// Presses on Menu button will generate a Menu key event. By default, not handling
// this event will cause the application to return to Headboard (tvOS launcher).
// When handling the event (for example, as a back button), both press and
// release events must be handled accordingly.
+ if (!qApp->focusWindow())
+ return false;
+
+ bool eventHandled = false;
+ const bool imEnabled = QIOSInputContext::instance()->inputMethodAccepted();
- bool handled = false;
for (UIPress* press in presses) {
Qt::KeyboardModifiers qtModifiers = Qt::NoModifier;
if (@available(ios 13.4, *))
@@ -645,26 +665,15 @@ inline ulong getTimeStamp(UIEvent *event)
int key = [self mapPressTypeToKey:press withModifiers:qtModifiers text:text];
if (key == Qt::Key_unknown)
continue;
- if (QWindowSystemInterface::handleKeyEvent(self.platformWindow->window(), type, key,
- qtModifiers, text)) {
- handled = true;
- }
- }
-
- return handled;
-}
+ if (imEnabled && ![self isControlKey:Qt::Key(key)])
+ continue;
-- (BOOL)handlePresses:(NSSet<UIPress *> *)presses eventType:(QEvent::Type)type
-{
- bool handlePress = false;
- if (qApp->focusWindow()) {
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
- if (qApp->focusObject() && QCoreApplication::sendEvent(qApp->focusObject(), &queryEvent))
- handlePress = queryEvent.value(Qt::ImEnabled).toBool();
- if (!handlePress && [self processPresses:presses withType:type])
- return true;
+ bool keyHandled = QWindowSystemInterface::handleKeyEvent(
+ self.platformWindow->window(), type, key, qtModifiers, text);
+ eventHandled = eventHandled || keyHandled;
}
- return false;
+
+ return eventHandled;
}
- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
@@ -676,14 +685,14 @@ inline ulong getTimeStamp(UIEvent *event)
- (void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
{
if (![self handlePresses:presses eventType:QEvent::KeyPress])
- [super pressesBegan:presses withEvent:event];
+ [super pressesChanged:presses withEvent:event];
[super pressesChanged:presses withEvent:event];
}
- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
{
if (![self handlePresses:presses eventType:QEvent::KeyRelease])
- [super pressesBegan:presses withEvent:event];
+ [super pressesEnded:presses withEvent:event];
[super pressesEnded:presses withEvent:event];
}
diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h
index 3853a0afa4..93b240c29c 100644
--- a/src/plugins/platforms/windows/qtwindowsglobal.h
+++ b/src/plugins/platforms/windows/qtwindowsglobal.h
@@ -93,7 +93,7 @@ QT_BEGIN_NAMESPACE
namespace QtWindows
{
-enum
+enum WindowsEventTypeFlags
{
WindowEventFlag = 0x10000,
MouseEventFlag = 0x20000,
@@ -174,6 +174,8 @@ enum WindowsEventType // Simplify event types
GestureEvent = 124,
UnknownEvent = 542
};
+Q_DECLARE_MIXED_ENUM_OPERATORS(bool, WindowsEventTypeFlags, WindowsEventType);
+Q_DECLARE_MIXED_ENUM_OPERATORS(bool, WindowsEventType, WindowsEventTypeFlags);
// Matches Process_DPI_Awareness (Windows 8.1 onwards), used for SetProcessDpiAwareness()
enum ProcessDpiAwareness
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index e7a5fb300d..24d4cf3043 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -680,6 +680,84 @@ IDropTargetHelper* QWindowsDrag::dropHelper() {
return m_cachedDropTargetHelper;
}
+// Workaround for DoDragDrop() not working with touch/pen input, causing DnD to hang until the mouse is moved.
+// We process pointer messages for touch/pen and generate mouse input through SendInput() to trigger DoDragDrop()
+static HRESULT startDoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource, DWORD dwOKEffects, LPDWORD pdwEffect)
+{
+ HWND hwnd = ::GetFocus();
+ bool starting = false;
+
+ for (;;) {
+ MSG msg{};
+ if (::GetMessage(&msg, hwnd, 0, 0) > 0) {
+
+ if (msg.message == WM_MOUSEMOVE) {
+
+ // Only consider the first simulated event, or actual mouse messages.
+ if (!starting && (msg.wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON | MK_XBUTTON1 | MK_XBUTTON2)) == 0)
+ return E_FAIL;
+
+ return ::DoDragDrop(pDataObj, pDropSource, dwOKEffects, pdwEffect);
+ }
+
+ if (msg.message == WM_POINTERUPDATE) {
+
+ const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
+
+ POINTER_INFO pointerInfo{};
+ if (!GetPointerInfo(pointerId, &pointerInfo))
+ return E_FAIL;
+
+ if (pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY) {
+
+ DWORD flags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_VIRTUALDESK | MOUSEEVENTF_MOVE;
+ if (IS_POINTER_FIRSTBUTTON_WPARAM(msg.wParam))
+ flags |= MOUSEEVENTF_LEFTDOWN;
+ if (IS_POINTER_SECONDBUTTON_WPARAM(msg.wParam))
+ flags |= MOUSEEVENTF_RIGHTDOWN;
+ if (IS_POINTER_THIRDBUTTON_WPARAM(msg.wParam))
+ flags |= MOUSEEVENTF_MIDDLEDOWN;
+
+ if (!starting) {
+ POINT pt{};
+ if (::GetCursorPos(&pt)) {
+
+ // Send mouse input that can generate a WM_MOUSEMOVE message.
+ if ((flags & MOUSEEVENTF_LEFTDOWN || flags & MOUSEEVENTF_RIGHTDOWN || flags & MOUSEEVENTF_MIDDLEDOWN)
+ && (pt.x != pointerInfo.ptPixelLocation.x || pt.y != pointerInfo.ptPixelLocation.y)) {
+
+ const int origin_x = ::GetSystemMetrics(SM_XVIRTUALSCREEN);
+ const int origin_y = ::GetSystemMetrics(SM_YVIRTUALSCREEN);
+ const int virt_w = ::GetSystemMetrics(SM_CXVIRTUALSCREEN);
+ const int virt_h = ::GetSystemMetrics(SM_CYVIRTUALSCREEN);
+ const int virt_x = pointerInfo.ptPixelLocation.x - origin_x;
+ const int virt_y = pointerInfo.ptPixelLocation.y - origin_y;
+
+ INPUT input{};
+ input.type = INPUT_MOUSE;
+ input.mi.dx = static_cast<DWORD>(virt_x * (65535.0 / virt_w));
+ input.mi.dy = static_cast<DWORD>(virt_y * (65535.0 / virt_h));
+ input.mi.dwFlags = flags;
+
+ ::SendInput(1, &input, sizeof(input));
+ starting = true;
+ }
+ }
+ }
+ }
+ } else {
+ // Handle other messages.
+ qWindowsWndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
+
+ if (msg.message == WM_POINTERLEAVE)
+ return E_FAIL;
+ }
+ } else {
+ return E_FAIL;
+ }
+ }
+}
+
Qt::DropAction QWindowsDrag::drag(QDrag *drag)
{
// TODO: Accessibility handling?
@@ -697,7 +775,7 @@ Qt::DropAction QWindowsDrag::drag(QDrag *drag)
<< Qt::hex << int(possibleActions) << "effects=0x" << allowedEffects << Qt::dec;
// Indicate message handlers we are in DoDragDrop() event loop.
QWindowsDrag::m_dragging = true;
- const HRESULT r = DoDragDrop(dropDataObject, windowDropSource, allowedEffects, &resultEffect);
+ const HRESULT r = startDoDragDrop(dropDataObject, windowDropSource, allowedEffects, &resultEffect);
QWindowsDrag::m_dragging = false;
const DWORD reportedPerformedEffect = dropDataObject->reportedPerformedEffect();
if (r == DRAGDROP_S_DROP) {
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index e7296c65a6..38e39edbcc 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -264,6 +264,7 @@ void QWindowsIntegrationPrivate::parseOptions(QWindowsIntegration *q, const QStr
QCoreApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents);
else
m_context.initTablet();
+ QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
if (!dpiAwarenessSet) { // Set only once in case of repeated instantiations of QGuiApplication.
if (!QCoreApplication::testAttribute(Qt::AA_PluginApplication)) {
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 5954f35b07..13a50f27a0 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -1403,7 +1403,7 @@ QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const
// Shift+9 over Alt + Shift + 9) resulting in more missing modifiers.
if (it == result.end())
result << matchedKey;
- else if (missingMods > (*it & Qt::KeyboardModifierMask))
+ else if (missingMods > Qt::KeyboardModifiers(*it & Qt::KeyboardModifierMask))
*it = matchedKey;
}
}
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index 7f8d0e54de..223e98a5b3 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -837,8 +837,8 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
break;
case QT_PT_PEN:
#if QT_CONFIG(tabletevent)
- if (!m_activeTabletDevice.isNull())
- device = m_activeTabletDevice.data();
+ qCDebug(lcQpaTablet) << "ignoring synth-mouse event for tablet event from" << device;
+ return false;
#endif
break;
}
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 2544dd6200..64abaf4cd1 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -204,11 +204,8 @@ static bool monitorData(HMONITOR hMonitor, QWindowsScreenData *data)
// EnumDisplayMonitors (as opposed to EnumDisplayDevices) enumerates only
// virtual desktop screens.
data->flags |= QWindowsScreenData::VirtualDesktop;
- if (info.dwFlags & MONITORINFOF_PRIMARY) {
+ if (info.dwFlags & MONITORINFOF_PRIMARY)
data->flags |= QWindowsScreenData::PrimaryScreen;
- if ((data->flags & QWindowsScreenData::LockScreen) == 0)
- QWindowsFontDatabase::setDefaultVerticalDPI(data->dpi.second);
- }
return true;
}
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index fa7a8be6a9..bb639a59bc 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -62,7 +62,6 @@
#include <QtCore/qvariant.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qdebug.h>
-#include <QtCore/qtextstream.h>
#include <QtCore/qoperatingsystemversion.h>
#include <QtCore/qsysinfo.h>
#include <QtCore/qcache.h>
@@ -94,17 +93,6 @@ static inline QColor COLORREFToQColor(COLORREF cr)
return QColor(GetRValue(cr), GetGValue(cr), GetBValue(cr));
}
-static inline QTextStream& operator<<(QTextStream &str, const QColor &c)
-{
- str.setIntegerBase(16);
- str.setFieldWidth(2);
- str.setPadChar(u'0');
- str << " rgb: #" << c.red() << c.green() << c.blue();
- str.setIntegerBase(10);
- str.setFieldWidth(0);
- return str;
-}
-
static inline bool booleanSystemParametersInfo(UINT what, bool defaultValue)
{
BOOL result;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
index ff4d6d77d4..3f6a63bb9e 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -107,10 +107,11 @@ QWindowsUiaMainProvider::~QWindowsUiaMainProvider()
void QWindowsUiaMainProvider::notifyFocusChange(QAccessibleEvent *event)
{
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
- // If this is a table/tree/list, raise event for the focused cell/item instead.
- if (accessible->tableInterface())
+ // If this is a complex element, raise event for the focused child instead.
+ if (accessible->childCount()) {
if (QAccessibleInterface *child = accessible->focusChild())
accessible = child;
+ }
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible))
QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_AutomationFocusChangedEventId);
}
diff --git a/src/plugins/platforms/xcb/CMakeLists.txt b/src/plugins/platforms/xcb/CMakeLists.txt
index 392b2c6cb6..c9dd456ab3 100644
--- a/src/plugins/platforms/xcb/CMakeLists.txt
+++ b/src/plugins/platforms/xcb/CMakeLists.txt
@@ -83,6 +83,8 @@ qt_internal_extend_target(XcbQpaPrivate CONDITION QT_FEATURE_draganddrop
)
qt_internal_extend_target(XcbQpaPrivate CONDITION QT_FEATURE_xcb_xlib
+ SOURCES
+ qt_xlib_wrapper.c qt_xlib_wrapper.h
PUBLIC_LIBRARIES
X11::XCB
# special case begin
diff --git a/src/plugins/platforms/xcb/qt_xlib_wrapper.c b/src/plugins/platforms/xcb/qt_xlib_wrapper.c
new file mode 100644
index 0000000000..3ff7120291
--- /dev/null
+++ b/src/plugins/platforms/xcb/qt_xlib_wrapper.c
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:COMM$
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** $QT_END_LICENSE$
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+******************************************************************************/
+
+#include "qt_xlib_wrapper.h"
+
+#include <X11/Xlib.h>
+
+void qt_XFlush(Display *dpy) { XFlush(dpy); }
diff --git a/src/plugins/platforms/xcb/qt_xlib_wrapper.h b/src/plugins/platforms/xcb/qt_xlib_wrapper.h
new file mode 100644
index 0000000000..3f77068348
--- /dev/null
+++ b/src/plugins/platforms/xcb/qt_xlib_wrapper.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:COMM$
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** $QT_END_LICENSE$
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+******************************************************************************/
+
+#ifndef QT_XLIB_WRAPPER_H
+#define QT_XLIB_WRAPPER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef struct _XDisplay Display;
+ void qt_XFlush(Display *dpy);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // QT_XLIB_WRAPPER_H
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 9bb069b70c..f4b829350a 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -71,6 +71,10 @@
#undef explicit
#include <xcb/xinput.h>
+#if QT_CONFIG(xcb_xlib)
+#include "qt_xlib_wrapper.h"
+#endif
+
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpaXInput, "qt.qpa.input")
@@ -1105,6 +1109,10 @@ void QXcbConnection::processXcbEvents(QEventLoop::ProcessEventsFlags flags)
m_eventQueue->flushBufferedEvents();
}
+#if QT_CONFIG(xcb_xlib)
+ qt_XFlush(static_cast<Display *>(xlib_display()));
+#endif
+
xcb_flush(xcb_connection());
}
diff --git a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
index 2df8de650c..6533288b2f 100644
--- a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
+++ b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
@@ -116,6 +116,20 @@ QGtk3Theme::QGtk3Theme()
/* Use our custom log handler. */
g_log_set_handler("Gtk", G_LOG_LEVEL_MESSAGE, gtkMessageHandler, nullptr);
+
+ /* Set XCURSOR_SIZE and XCURSOR_THEME for Wayland sessions */
+ if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"))) {
+ if (qEnvironmentVariableIsEmpty("XCURSOR_SIZE")) {
+ const int cursorSize = gtkSetting<gint>("gtk-cursor-theme-size");
+ if (cursorSize > 0)
+ qputenv("XCURSOR_SIZE", QString::number(cursorSize).toUtf8());
+ }
+ if (qEnvironmentVariableIsEmpty("XCURSOR_THEME")) {
+ const QString cursorTheme = gtkSetting("gtk-cursor-theme-name");
+ if (!cursorTheme.isEmpty())
+ qputenv("XCURSOR_THEME", cursorTheme.toUtf8());
+ }
+ }
}
static inline QVariant gtkGetLongPressTime()
@@ -190,7 +204,7 @@ QPlatformTheme::Appearance QGtk3Theme::appearance() const
gtk-theme-name provides both light and dark variants. We can save a
regex check by testing this property first.
*/
- const auto preferDark = gtkSetting<bool>("gtk-application-prefer-dark-theme");
+ const auto preferDark = gtkSetting<gboolean>("gtk-application-prefer-dark-theme");
if (preferDark)
return Appearance::Dark;
diff --git a/src/plugins/sqldrivers/.cmake.conf b/src/plugins/sqldrivers/.cmake.conf
index b9c40d1839..f6f7fed367 100644
--- a/src/plugins/sqldrivers/.cmake.conf
+++ b/src/plugins/sqldrivers/.cmake.conf
@@ -1 +1 @@
-set(QT_REPO_MODULE_VERSION "6.2.6")
+set(QT_REPO_MODULE_VERSION "6.2.7")
diff --git a/src/plugins/sqldrivers/oci/qsql_oci_p.h b/src/plugins/sqldrivers/oci/qsql_oci_p.h
index a3366abb77..ddd1fd88b5 100644
--- a/src/plugins/sqldrivers/oci/qsql_oci_p.h
+++ b/src/plugins/sqldrivers/oci/qsql_oci_p.h
@@ -78,7 +78,7 @@ public:
explicit QOCIDriver(QObject *parent = nullptr);
QOCIDriver(OCIEnv *env, OCISvcCtx *ctx, QObject *parent = nullptr);
~QOCIDriver();
- bool hasFeature(DriverFeature f) const;
+ bool hasFeature(DriverFeature f) const override;
bool open(const QString &db,
const QString &user,
const QString &password,
diff --git a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
index dc65e3a4e4..a789ebf5a1 100644
--- a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
+++ b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
@@ -404,7 +404,7 @@ static QMetaType qDecodeODBCType(SQLSMALLINT sqltype, bool isSigned = true)
return QMetaType(type);
}
-static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool unicode = false)
+static QVariant qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool unicode)
{
QString fieldVal;
SQLRETURN r = SQL_ERROR;
@@ -438,8 +438,7 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni
&lengthIndicator);
if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
if (lengthIndicator == SQL_NULL_DATA) {
- fieldVal.clear();
- break;
+ return {};
}
// starting with ODBC Native Client 2012, SQL_NO_TOTAL is returned
// instead of the length (which sometimes was wrong in older versions)
@@ -465,8 +464,7 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni
break;
} else {
qWarning() << "qGetStringData: Error while fetching data (" << qWarnODBCHandle(SQL_HANDLE_STMT, hStmt) << ')';
- fieldVal.clear();
- break;
+ return {};
}
}
} else {
@@ -488,8 +486,7 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni
&lengthIndicator);
if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
if (lengthIndicator == SQL_NULL_DATA || lengthIndicator == SQL_NO_TOTAL) {
- fieldVal.clear();
- break;
+ return {};
}
// if SQL_SUCCESS_WITH_INFO is returned, indicating that
// more data can be fetched, the length indicator does NOT
@@ -509,8 +506,7 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni
break;
} else {
qWarning() << "qGetStringData: Error while fetching data (" << qWarnODBCHandle(SQL_HANDLE_STMT, hStmt) << ')';
- fieldVal.clear();
- break;
+ return {};
}
}
}
@@ -654,7 +650,7 @@ static QSqlField qMakeFieldInfo(const SQLHANDLE hStmt, int i, QString *errorMess
// by SQLColumns. The hStmt has to point to a valid position.
static QSqlField qMakeFieldInfo(const SQLHANDLE hStmt, const QODBCDriverPrivate* p)
{
- QString fname = qGetStringData(hStmt, 3, -1, p->unicode);
+ QString fname = qGetStringData(hStmt, 3, -1, p->unicode).toString();
int type = qGetIntData(hStmt, 4).toInt(); // column type
QSqlField f(fname, qDecodeODBCType(type, p));
QVariant var = qGetIntData(hStmt, 6);
@@ -1295,7 +1291,7 @@ QVariant QODBCResult::data(int field)
}
break;
default:
- d->fieldCache[i] = QVariant(qGetStringData(d->hStmt, i, info.length(), false));
+ d->fieldCache[i] = qGetStringData(d->hStmt, i, info.length(), false);
break;
}
d->fieldCacheIdx = field + 1;
@@ -1308,7 +1304,7 @@ bool QODBCResult::isNull(int field)
Q_D(const QODBCResult);
if (field < 0 || field >= d->fieldCache.size())
return true;
- if (field <= d->fieldCacheIdx) {
+ if (field >= d->fieldCacheIdx) {
// since there is no good way to find out whether the value is NULL
// without fetching the field we'll fetch it here.
// (data() also sets the NULL flag)
@@ -2426,8 +2422,7 @@ QStringList QODBCDriver::tables(QSql::TableType type) const
}
while (r == SQL_SUCCESS) {
- QString fieldVal = qGetStringData(hStmt, 2, -1, d->unicode);
- tl.append(fieldVal);
+ tl.append(qGetStringData(hStmt, 2, -1, d->unicode).toString());
if (d->hasSQLFetchScroll)
r = SQLFetchScroll(hStmt,
@@ -2524,11 +2519,11 @@ QSqlIndex QODBCDriver::primaryIndex(const QString& tablename) const
// Store all fields in a StringList because some drivers can't detail fields in this FETCH loop
while (r == SQL_SUCCESS) {
if (usingSpecialColumns) {
- cName = qGetStringData(hStmt, 1, -1, d->unicode); // column name
+ cName = qGetStringData(hStmt, 1, -1, d->unicode).toString(); // column name
idxName = QString::number(fakeId++); // invent a fake index name
} else {
- cName = qGetStringData(hStmt, 3, -1, d->unicode); // column name
- idxName = qGetStringData(hStmt, 5, -1, d->unicode); // pk index name
+ cName = qGetStringData(hStmt, 3, -1, d->unicode).toString(); // column name
+ idxName = qGetStringData(hStmt, 5, -1, d->unicode).toString(); // pk index name
}
index.append(rec.field(cName));
index.setName(idxName);
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index a20030f1a6..ae0029d415 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -468,7 +468,9 @@ static bool setupSlider(NSSlider *slider, const QStyleOptionSlider *sl)
// NSSlider seems to cache values based on tracking and the last layout of the
// NSView, resulting in incorrect knob rects that break the interaction with
// multiple sliders. So completely reinitialize the slider.
+ const auto controlSize = slider.controlSize;
[slider initWithFrame:sl->rect.toCGRect()];
+ slider.controlSize = controlSize;
slider.minValue = sl->minimum;
slider.maxValue = sl->maximum;
@@ -1828,10 +1830,6 @@ QRectF QMacStylePrivate::comboboxEditBounds(const QRectF &outerBounds, const Coc
QMacStylePrivate::QMacStylePrivate()
: backingStoreNSView(nil)
{
- if (auto *ssf = QGuiApplicationPrivate::platformTheme()->font(QPlatformTheme::SmallFont))
- smallSystemFont = *ssf;
- if (auto *msf = QGuiApplicationPrivate::platformTheme()->font(QPlatformTheme::MiniFont))
- miniSystemFont = *msf;
}
QMacStylePrivate::~QMacStylePrivate()
@@ -2126,6 +2124,14 @@ void QMacStyle::unpolish(QApplication *)
void QMacStyle::polish(QWidget* w)
{
+ Q_D(QMacStyle);
+ if (!d->smallSystemFont && QGuiApplicationPrivate::platformTheme()) {
+ if (auto *ssf = QGuiApplicationPrivate::platformTheme()->font(QPlatformTheme::SmallFont))
+ d->smallSystemFont = *ssf;
+ else
+ d->smallSystemFont = QFont();
+ }
+
if (false
#if QT_CONFIG(menu)
|| qobject_cast<QMenu*>(w)
@@ -3996,8 +4002,13 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
pb.enabled = isEnabled;
[pb highlight:isPressed];
+
// Set off state when inactive. See needsInactiveHack for when it's selected
- pb.state = (isActive && isSelected && !isPressed) ? NSControlStateValueOn : NSControlStateValueOff;
+ // On macOS 12, don't set the Off state for selected tabs as it draws a gray backgorund even when highlighted
+ if (QOperatingSystemVersion::current() > QOperatingSystemVersion::MacOSBigSur)
+ pb.state = (isActive && isSelected) ? NSControlStateValueOn : NSControlStateValueOff;
+ else
+ pb.state = (isActive && isSelected && !isPressed) ? NSControlStateValueOn : NSControlStateValueOff;
const auto drawBezelBlock = ^(CGContextRef ctx, const CGRect &r) {
CGContextClipToRect(ctx, opt->rect.toCGRect());
@@ -5746,8 +5757,8 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
const bool rtl = groupBox.direction == Qt::RightToLeft;
const int alignment = Qt::TextHideMnemonic | (rtl ? Qt::AlignRight : Qt::AlignLeft);
const QFont savedFont = p->font();
- if (!flat)
- p->setFont(d->smallSystemFont);
+ if (!flat && d->smallSystemFont)
+ p->setFont(*d->smallSystemFont);
proxy()->drawItemText(p, rect, alignment, groupBox.palette, groupBox.state & State_Enabled, groupBox.text, QPalette::WindowText);
if (!flat)
p->setFont(savedFont);
@@ -6111,7 +6122,9 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
const int margin = flat || hasNoText ? 0 : 9;
ret = groupBox->rect.adjusted(margin, 0, -margin, 0);
- const QFontMetricsF fm = flat || fontIsSet ? QFontMetricsF(groupBox->fontMetrics) : QFontMetricsF(d->smallSystemFont);
+ const QFontMetricsF fm = flat || fontIsSet || !d->smallSystemFont
+ ? QFontMetricsF(groupBox->fontMetrics)
+ : QFontMetricsF(*d->smallSystemFont);
const QSizeF s = fm.size(Qt::AlignHCenter | Qt::AlignVCenter, qt_mac_removeMnemonics(groupBox->text), 0, nullptr);
const int tw = qCeil(s.width());
const int h = qCeil(fm.height());
diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
index 6305a0ea1f..a069a8f56f 100644
--- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h
+++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
@@ -298,8 +298,7 @@ public:
mutable QHash<CocoaControl, NSView *> cocoaControls;
mutable QHash<CocoaControl, NSCell *> cocoaCells;
- QFont smallSystemFont;
- QFont miniSystemFont;
+ std::optional<QFont> smallSystemFont;
QMacKeyValueObserver appearanceObserver;
};
diff --git a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
index 67d6b0c460..4ae5ad24b9 100644
--- a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
+++ b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
@@ -86,6 +86,12 @@ bool QWindowsVistaStylePrivate::useVista()
return QWindowsVistaStylePrivate::useXP();
}
+namespace QOSWorkaround {
+ // Qt 6.2's QOperatingSystemVersion doesn't know about Windows 11
+ static const QOperatingSystemVersion Windows11(QOperatingSystemVersion::Windows,
+ 10, 0, 22000);
+}
+
/* \internal
Checks and returns the style object
*/
@@ -1261,6 +1267,9 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
else
theme.stateId = bullet ? MC_BULLETNORMAL: MC_CHECKMARKNORMAL;
d->drawBackground(theme);
+ } else if (QOperatingSystemVersion::current() >= QOSWorkaround::Windows11
+ && !act) {
+ painter->fillRect(checkRect, menuitem->palette.highlight().color().lighter(200));
}
}
diff --git a/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp b/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp
index 9a4dcb6861..d6e3c5c37c 100644
--- a/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp
+++ b/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp
@@ -676,6 +676,12 @@ static QStringList findAllLibCrypto()
}
# endif
+#if (OPENSSL_VERSION_NUMBER >> 28) < 3
+#define QT_OPENSSL_VERSION "1_1"
+#elif OPENSSL_VERSION_MAJOR == 3 // Starting with 3.0 this define is available
+#define QT_OPENSSL_VERSION "3"
+#endif // > 3 intentionally left undefined
+
#ifdef Q_OS_WIN
struct LoadedOpenSsl {
@@ -707,12 +713,6 @@ static LoadedOpenSsl loadOpenSsl()
// MSVC and GCC. For 3.0 the version suffix changed again, to just '3'.
// For non-x86 builds, an architecture suffix is also appended.
-#if (OPENSSL_VERSION_NUMBER >> 28) < 3
-#define QT_OPENSSL_VERSION "1_1"
-#elif OPENSSL_VERSION_MAJOR == 3 // Starting with 3.0 this define is available
-#define QT_OPENSSL_VERSION "3"
-#endif // > 3 intentionally left undefined
-
#if defined(Q_PROCESSOR_X86_64)
#define QT_SSL_SUFFIX "-x64"
#elif defined(Q_PROCESSOR_ARM_64)
@@ -729,7 +729,7 @@ static LoadedOpenSsl loadOpenSsl()
#undef QT_SSL_SUFFIX
return result;
}
-#else
+#else // !Q_OS_WIN:
struct LoadedOpenSsl {
std::unique_ptr<QLibrary> ssl, crypto;
@@ -808,7 +808,7 @@ static LoadedOpenSsl loadOpenSsl()
return suffix;
};
- static QString suffix = QString::fromLatin1(openSSLSuffix("_1_1"));
+ static QString suffix = QString::fromLatin1(openSSLSuffix("_" QT_OPENSSL_VERSION));
libssl->setFileNameAndVersion(QLatin1String("ssl") + suffix, -1);
libcrypto->setFileNameAndVersion(QLatin1String("crypto") + suffix, -1);