diff options
27 files changed, 253 insertions, 57 deletions
diff --git a/cmake/QtInternalTargets.cmake b/cmake/QtInternalTargets.cmake index 0ef27717502..2985d2edce9 100644 --- a/cmake/QtInternalTargets.cmake +++ b/cmake/QtInternalTargets.cmake @@ -46,17 +46,8 @@ function(qt_internal_set_warnings_are_errors_flags target target_scope) # error: assuming signed overflow does not occur when assuming that (X + c) < X # is always false -Wno-error=strict-overflow - CONDITIONS VERSION_GREATER_EQUAL 7 - OPTIONS - # GCC 7 includes -Wimplicit-fallthrough in -Wextra, but Qt is not yet free of - # implicit fallthroughs. - -Wno-error=implicit-fallthrough CONDITIONS VERSION_GREATER_EQUAL 9 OPTIONS - # GCC 9 introduced these but we are not clean for it. - -Wno-error=deprecated-copy - -Wno-error=redundant-move - -Wno-error=init-list-lifetime # GCC 9 introduced -Wformat-overflow in -Wall, but it is buggy: -Wno-error=format-overflow CONDITIONS VERSION_GREATER_EQUAL 10 diff --git a/cmake/QtPublicSbomQtEntityHelpers.cmake b/cmake/QtPublicSbomQtEntityHelpers.cmake index d8d61eef42c..1ccc64421b1 100644 --- a/cmake/QtPublicSbomQtEntityHelpers.cmake +++ b/cmake/QtPublicSbomQtEntityHelpers.cmake @@ -234,9 +234,8 @@ function(_qt_internal_sbom_handle_qt_entity_cpe target) set(cpe_list "") - # Add the qt-specific CPE if the target is a Qt entity type, or if it's a 3rd party entity type - # without any CPE specified. - if(is_qt_entity_type OR (is_qt_3rd_party_entity_type AND NOT arg_CPE)) + # Add the qt-specific CPE if the target is a Qt entity type + if(is_qt_entity_type) _qt_internal_sbom_compute_security_cpe_for_qt(cpe_list) endif() diff --git a/doc/global/disabledwarnings.qdocconf b/doc/global/disabledwarnings.qdocconf index c0070fca610..6da39a84e9b 100644 --- a/doc/global/disabledwarnings.qdocconf +++ b/doc/global/disabledwarnings.qdocconf @@ -1,4 +1,5 @@ spurious = \ + "Undocumented property \*" \ "Missing comma in .*" \ "Missing pattern .*" \ "Unable to parse (QML|JavaScript).*" \ diff --git a/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java index 1d4ec370d39..93407d52e95 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java @@ -241,12 +241,15 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate return; } - final AccessibilityEvent event = - obtainAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT); + final CharSequence className = getNodeForVirtualViewId(viewId).getClassName(); + final int eventType = + className != null && className.equals("android.widget.ProgressBar") + ? AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED + : AccessibilityEvent.TYPE_ANNOUNCEMENT; + final AccessibilityEvent event = obtainAccessibilityEvent(eventType); event.setEnabled(true); - event.setClassName(getNodeForVirtualViewId(viewId).getClassName()); - + event.setClassName(className); event.setContentDescription(value); if (event.getText().isEmpty() && TextUtils.isEmpty(event.getContentDescription())) { diff --git a/src/corelib/global/qcompilerdetection.qdoc b/src/corelib/global/qcompilerdetection.qdoc index 9b49a1491ab..e64dca74667 100644 --- a/src/corelib/global/qcompilerdetection.qdoc +++ b/src/corelib/global/qcompilerdetection.qdoc @@ -277,6 +277,18 @@ \row \li \c{constexpr} \li C++11 \li yes \li required \row \li \c{constinit} \li C++20 \li no \li required \endtable + + If declaration and definition of a Q_CONSTINIT variable are separate, this + macro goes only on the definition, and not on the declaration: + + \code + class C { + ~~~~ + static int count; // declaration, no Q_CONSTINIT here + }; + ~~~ + Q_CONSTINIT int C::count = 0; // definition + \endcode */ /*! diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index dc7d90f4b30..8d545242095 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -699,7 +699,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel Returns the minimum value that QRandomGenerator may ever generate. That is, 0. - \sa max(), QRandomGenerator64::min() + \sa max() */ /*! @@ -708,7 +708,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel Returns the maximum value that QRandomGenerator may ever generate. That is, \c {std::numeric_limits<result_type>::max()}. - \sa min(), QRandomGenerator64::max() + \sa min() */ /*! diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 9b219d089b5..9117c827afe 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -377,7 +377,7 @@ public: >::value) : QVariant(std::in_place, QMetaType::fromType<q20::remove_cvref_t<T>>()) { - char *data = static_cast<char *>(const_cast<void *>(constData())); + void *data = const_cast<void *>(constData()); new (data) T(il, std::forward<Args>(args)...); } diff --git a/src/corelib/tools/qmultimap.qdoc b/src/corelib/tools/qmultimap.qdoc index fdf65f28876..dc705fdb2eb 100644 --- a/src/corelib/tools/qmultimap.qdoc +++ b/src/corelib/tools/qmultimap.qdoc @@ -457,7 +457,7 @@ Returns the number of items associated with key \a key. - \sa contains(), QMultiMap::count() + \sa contains(), QMultiMap::count(const Key &key, const T &value) */ /*! \fn template <class Key, class T> qsizetype QMultiMap<Key, T>::count(const Key &key, const T &value) const diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h index 1e16f42626b..f4b50b07d8a 100644 --- a/src/gui/image/qicon.h +++ b/src/gui/image/qicon.h @@ -265,6 +265,8 @@ private: friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QIcon &); #endif + friend class QIconPrivate; + public: typedef QIconPrivate * DataPtr; inline DataPtr &data_ptr() { return d; } diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h index 60985d538dc..29d88f8f222 100644 --- a/src/gui/image/qicon_p.h +++ b/src/gui/image/qicon_p.h @@ -34,6 +34,11 @@ public: delete engine; } + static QIconPrivate *get(QIcon *icon) { return icon->d; } + static const QIconPrivate *get(const QIcon *icon) { return icon->d; } + + enum IconEngineHook { PlatformIconHook = 1000 }; + static qreal pixmapDevicePixelRatio(qreal displayDevicePixelRatio, const QSize &requestedSize, const QSize &actualSize); QIconEngine *engine; diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 7b1e76cc78f..a95f94dea7e 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -4211,7 +4211,8 @@ QDebug operator<<(QDebug dbg, const QEvent *e) const Qt::MouseButtons buttons = spe->buttons(); dbg << eventClassName(type) << '('; QtDebugUtils::formatQEnum(dbg, type); - dbg << " ts=" << spe->timestamp(); + if (dbg.verbosity() > QDebug::DefaultVerbosity) + dbg << " ts=" << spe->timestamp(); if (isMouse) { if (type != QEvent::MouseMove && type != QEvent::NonClientAreaMouseMove) { dbg << ' '; @@ -4338,6 +4339,8 @@ QDebug operator<<(QDebug dbg, const QEvent *e) const QNativeGestureEvent *ne = static_cast<const QNativeGestureEvent *>(e); dbg << "QNativeGestureEvent("; QtDebugUtils::formatQEnum(dbg, ne->gestureType()); + if (dbg.verbosity() > QDebug::DefaultVerbosity) + dbg << ", ts=" << ne->timestamp(); dbg << ", fingerCount=" << ne->fingerCount() << ", localPos="; QtDebugUtils::formatQPoint(dbg, ne->position()); if (!qIsNull(ne->value())) diff --git a/src/gui/painting/qcoregraphics.mm b/src/gui/painting/qcoregraphics.mm index dfdfa8f84e7..819f3c8e5d2 100644 --- a/src/gui/painting/qcoregraphics.mm +++ b/src/gui/painting/qcoregraphics.mm @@ -11,6 +11,7 @@ #include <QtCore/qcoreapplication.h> #include <QtCore/qoperatingsystemversion.h> #include <QtGui/qcolorspace.h> +#include <QtGui/private/qicon_p.h> #if defined(Q_OS_MACOS) # include <AppKit/AppKit.h> @@ -303,6 +304,26 @@ QImage qt_mac_toQImage(CGImageRef cgImage) return image; } +QImage qt_mac_padToSquareImage(const QImage &image) +{ + if (image.width() == image.height()) + return image; + + const int size = std::max(image.width(), image.height()); + QImage squareImage(size, size, image.format()); + squareImage.setDevicePixelRatio(image.devicePixelRatio()); + squareImage.fill(Qt::transparent); + + QPoint pos((size - image.width()) / (2.0 * image.devicePixelRatio()), + (size - image.height()) / (2.0 * image.devicePixelRatio())); + + QPainter painter(&squareImage); + painter.drawImage(pos, image); + painter.end(); + + return squareImage; +} + #ifdef Q_OS_MACOS QT_END_NAMESPACE @@ -383,6 +404,19 @@ QT_END_NAMESPACE return nsImage; } + ++ (instancetype)internalImageFromQIcon:(const QT_PREPEND_NAMESPACE(QIcon) &)icon +{ + if (icon.isNull()) + return nil; + + // Check if the icon is backed by an NSImage. If so, we can use that directly. + auto *iconPrivate = QIconPrivate::get(&icon); + NSImage *iconImage = nullptr; + iconPrivate->engine->virtual_hook(QIconPrivate::PlatformIconHook, &iconImage); + return iconImage; +} + @end QT_BEGIN_NAMESPACE diff --git a/src/gui/painting/qcoregraphics_p.h b/src/gui/painting/qcoregraphics_p.h index 7bec19ffb98..9d176516d56 100644 --- a/src/gui/painting/qcoregraphics_p.h +++ b/src/gui/painting/qcoregraphics_p.h @@ -66,6 +66,7 @@ QT_END_NAMESPACE withSize:(const QT_PREPEND_NAMESPACE(QSize) &)size withMode:(QT_PREPEND_NAMESPACE(QIcon)::Mode)mode withState:(QT_PREPEND_NAMESPACE(QIcon)::State)state; ++ (instancetype)internalImageFromQIcon:(const QT_PREPEND_NAMESPACE(QIcon) &)icon; @end QT_BEGIN_NAMESPACE #endif // __OBJC__ @@ -74,6 +75,8 @@ QT_BEGIN_NAMESPACE Q_GUI_EXPORT CGImageRef qt_mac_toCGImage(const QImage &qImage); Q_GUI_EXPORT QImage qt_mac_toQImage(CGImageRef image); +Q_GUI_EXPORT QImage qt_mac_padToSquareImage(const QImage &image); + Q_GUI_EXPORT void qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage); Q_GUI_EXPORT void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig_xform); diff --git a/src/gui/painting/qdrawhelper_avx2.cpp b/src/gui/painting/qdrawhelper_avx2.cpp index d7496845197..a736b75dab2 100644 --- a/src/gui/painting/qdrawhelper_avx2.cpp +++ b/src/gui/painting/qdrawhelper_avx2.cpp @@ -38,6 +38,7 @@ BYTE_MUL_AVX2(__m256i &pixelVector, __m256i alphaChannel, __m256i colorMask, __m pixelVector = _mm256_blendv_epi8(pixelVectorAG, pixelVectorRB, colorMask); } +#if QT_CONFIG(raster_64bit) inline static void Q_DECL_VECTORCALL BYTE_MUL_RGB64_AVX2(__m256i &pixelVector, __m256i alphaChannel, __m256i colorMask, __m256i half) { @@ -55,6 +56,7 @@ BYTE_MUL_RGB64_AVX2(__m256i &pixelVector, __m256i alphaChannel, __m256i colorMas pixelVectorRB = _mm256_srli_epi32(pixelVectorRB, 16); pixelVector = _mm256_blendv_epi8(pixelVectorAG, pixelVectorRB, colorMask); } +#endif // See INTERPOLATE_PIXEL_255_SSE2 for details. inline static void Q_DECL_VECTORCALL @@ -79,6 +81,7 @@ INTERPOLATE_PIXEL_255_AVX2(__m256i srcVector, __m256i &dstVector, __m256i alphaC dstVector = _mm256_blendv_epi8(finalAG, finalRB, colorMask); } +#if QT_CONFIG(raster_64bit) inline static void Q_DECL_VECTORCALL INTERPOLATE_PIXEL_RGB64_AVX2(__m256i srcVector, __m256i &dstVector, __m256i alphaChannel, __m256i oneMinusAlphaChannel, __m256i colorMask, __m256i half) { @@ -99,6 +102,7 @@ INTERPOLATE_PIXEL_RGB64_AVX2(__m256i srcVector, __m256i &dstVector, __m256i alph finalRB = _mm256_srli_epi32(finalRB, 16); dstVector = _mm256_blendv_epi8(finalAG, finalRB, colorMask); } +#endif // See BLEND_SOURCE_OVER_ARGB32_SSE2 for details. inline static void Q_DECL_VECTORCALL BLEND_SOURCE_OVER_ARGB32_AVX2(quint32 *dst, const quint32 *src, const int length) diff --git a/src/gui/platform/darwin/qappleiconengine.mm b/src/gui/platform/darwin/qappleiconengine.mm index 3228b97fdb0..925135e9621 100644 --- a/src/gui/platform/darwin/qappleiconengine.mm +++ b/src/gui/platform/darwin/qappleiconengine.mm @@ -15,6 +15,7 @@ #include <QtGui/qstylehints.h> #include <QtGui/private/qcoregraphics_p.h> +#include <QtGui/private/qicon_p.h> QT_BEGIN_NAMESPACE @@ -302,6 +303,11 @@ QAppleIconEngine::~QAppleIconEngine() [m_image release]; } +QIcon QAppleIconEngine::fromTheme(const QString &iconName) +{ + return QIcon(new QAppleIconEngine(iconName)); +} + QIconEngine *QAppleIconEngine::clone() const { return new QAppleIconEngine(m_iconName); @@ -476,4 +482,14 @@ void QAppleIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode m #endif } +void QAppleIconEngine::virtual_hook(int hookIdentifier, void *data) +{ + // Expose underlying NSImage so we can pass it on to AppKit + // directly without flattening, preserving the symbol image. + if (hookIdentifier == QIconPrivate::PlatformIconHook) + *static_cast<decltype(m_image)*>(data) = m_image; + else + QIconEngine::virtual_hook(hookIdentifier, data); +} + QT_END_NAMESPACE diff --git a/src/gui/platform/darwin/qappleiconengine_p.h b/src/gui/platform/darwin/qappleiconengine_p.h index 7d20896517b..b71386ca63a 100644 --- a/src/gui/platform/darwin/qappleiconengine_p.h +++ b/src/gui/platform/darwin/qappleiconengine_p.h @@ -31,6 +31,9 @@ class Q_GUI_EXPORT QAppleIconEngine : public QIconEngine public: QAppleIconEngine(const QString &iconName); ~QAppleIconEngine(); + + static QIcon fromTheme(const QString &iconName); + QIconEngine *clone() const override; QString key() const override; QString iconName() override; @@ -44,6 +47,8 @@ public: static QList<QSize> availableIconSizes(double aspectRatio = 1.0); + void virtual_hook(int hookIdentifier, void *data) override; + private: const QString m_iconName; #if defined(Q_OS_MACOS) diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index 481ffd57b5d..a511eb854cb 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -406,7 +406,9 @@ static inline VmaAllocator toVmaAllocator(QVkAllocator a) QByteArrayList QRhiVulkanInitParams::preferredInstanceExtensions() { return { - QByteArrayLiteral("VK_KHR_get_physical_device_properties2") + QByteArrayLiteral("VK_KHR_get_physical_device_properties2"), + // to silence validation when e.g. on Wayland a surface format's colorspace is VK_COLOR_SPACE_PASS_THROUGH_EXT + QByteArrayLiteral("VK_EXT_swapchain_colorspace") }; } diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 13f1a19a360..705429e5ccf 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -441,10 +441,22 @@ QPlatformKeyMapper *QCocoaIntegration::keyMapper() const void QCocoaIntegration::setApplicationIcon(const QIcon &icon) const { - // Fall back to a size that looks good on the highest resolution screen available + if (icon.isNull()) { + NSApp.applicationIconImage = nil; + return; + } + + // Request a size that looks good on the highest resolution screen available // for icon engines that don't have an intrinsic size (like SVG). - auto fallbackSize = QSizeF::fromCGSize(NSApp.dockTile.size) * qGuiApp->devicePixelRatio(); - NSApp.applicationIconImage = [NSImage imageFromQIcon:icon withSize:fallbackSize.toSize()]; + const auto dockTitleSize = QSizeF::fromCGSize(NSApp.dockTile.size).toSize(); + auto image = icon.pixmap(dockTitleSize, qGuiApp->devicePixelRatio()).toImage(); + + // The assigned image is scaled by the system to fit into the tile, + // but without taking aspect ratio into account, so let's pad the + // image up front if it's not already square. + image = qt_mac_padToSquareImage(image); + + NSApp.applicationIconImage = [NSImage imageFromQImage:image]; } void QCocoaIntegration::setApplicationBadge(qint64 number) diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index ca43ab421e0..a9a79665f7d 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -373,11 +373,21 @@ NSMenuItem *QCocoaMenuItem::sync() m_native.keyEquivalentModifierMask = NSEventModifierFlagCommand; } - const QIcon::Mode mode = m_enabled ? QIcon::Normal : QIcon::Disabled; - const QIcon::State state = m_checked ? QIcon::On : QIcon::Off; - m_native.image = [NSImage imageFromQIcon:m_icon withSize:QSize(m_iconSize, m_iconSize) - withMode:mode - withState:state]; + if (auto *image = [NSImage internalImageFromQIcon:m_icon]) { + // The icon is backed by QAppleIconEngine, in which case we + // want to pass on the underlying NSImage instead of flattening + // to a QImage, as AppKit takes care of requesting a symbol + // configuration that matches the size and look of the menu, + // which we can't replicate otherwise. Note that this ignores + // any possible explicitly set icon size of the menu item. + m_native.image = [[image copy] autorelease]; + } else { + const QIcon::Mode mode = m_enabled ? QIcon::Normal : QIcon::Disabled; + const QIcon::State state = m_checked ? QIcon::On : QIcon::Off; + m_native.image = [NSImage imageFromQIcon:m_icon withSize:QSize(m_iconSize, m_iconSize) + withMode:mode + withState:state]; + } m_native.state = m_checked ? NSControlStateValueOn : NSControlStateValueOff; return m_native; diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm index 1505357ee40..d5c5ed8c2e2 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm @@ -85,6 +85,19 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) if (!m_statusItem) return; + if (auto *image = [NSImage internalImageFromQIcon:icon]) { + // The icon is backed by QAppleIconEngine, in which case we + // want to pass on the underlying NSImage instead of flattening + // to a QImage. This preserves the isTemplate property of the + // image, and allows AppKit to size and configure the icon for + // the status bar. We also enable NSVariableStatusItemLength, + // to match the behavior of SwiftUI's MenuBarExtra. + m_statusItem.button.image = [[image copy] autorelease]; + m_statusItem.button.imageScaling = NSImageScaleProportionallyDown; + m_statusItem.length = NSVariableStatusItemLength; + return; + } + // The recommended maximum title bar icon height is 18 points // (device independent pixels). The menu height on past and // current OS X versions is 22 points. Provide some future-proofing @@ -206,7 +219,17 @@ void QCocoaSystemTrayIcon::showMessage(const QString &title, const QString &mess auto *notification = [[NSUserNotification alloc] init]; notification.title = title.toNSString(); notification.informativeText = message.toNSString(); - notification.contentImage = [NSImage imageFromQIcon:icon]; + + // Request a size that looks good on the highest resolution screen available + // for icon engines that don't have an intrinsic size (like SVG). + auto image = icon.pixmap(QSize(64, 64), qGuiApp->devicePixelRatio()).toImage(); + + // The assigned image is scaled by the system to fit into the tile, + // but without taking aspect ratio into account, so let's pad the + // image up front if it's not already square. + image = qt_mac_padToSquareImage(image); + + notification.contentImage = [NSImage imageFromQImage:image]; NSUserNotificationCenter *center = NSUserNotificationCenter.defaultUserNotificationCenter; center.delegate = m_delegate; diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm index f9094a8f665..52f449db08b 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.mm +++ b/src/plugins/platforms/cocoa/qcocoatheme.mm @@ -400,9 +400,9 @@ QPixmap QCocoaTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const iconType = kGenericDocumentIcon; break; case ToolBarHorizontalExtensionButton: - return QIcon::fromTheme("chevron.forward.2").pixmap(size.toSize()); + return QAppleIconEngine::fromTheme("chevron.forward.2").pixmap(size.toSize()); case ToolBarVerticalExtensionButton: - return QIcon::fromTheme("chevron.down.2").pixmap(size.toSize()); + return QAppleIconEngine::fromTheme("chevron.down.2").pixmap(size.toSize()); default: break; } diff --git a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp index 56fda45e905..ad5c498032c 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp @@ -28,6 +28,10 @@ #include <sys/ioctl.h> #endif +#if defined(Q_OS_VXWORKS) +#include <fbdev.h> +#endif + #include <private/qfactoryloader_p.h> #include <private/qcore_unix_p.h> @@ -270,6 +274,13 @@ void QEglFSDeviceIntegration::waitForVSync(QPlatformSurface *surface) const if (ioctl(framebuffer, FBIO_WAITFORVSYNC, &arg) == -1) qWarning("Could not wait for vsync."); } +#elif defined(Q_OS_VXWORKS) && defined(FB_IOCTL_VSYNC) + static const bool forceSync = qEnvironmentVariableIntValue("QT_QPA_EGLFS_FORCEVSYNC"); + if (forceSync && framebuffer != -1) { + int arg = 0; + if (ioctl(framebuffer, FB_IOCTL_VSYNC, &arg) == -1) + qWarning("Could not wait for vsync."); + } #endif } diff --git a/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm b/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm index 6ca6554f673..c173aa426fc 100644 --- a/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm +++ b/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm @@ -28,6 +28,19 @@ docTypes = [self computeAllowedFileTypes:results]; } + // FIXME: Handle security scoped URLs instead of copying resource + bool asCopy = [&]{ + switch (fileDialog->options()->fileMode()) { + case QFileDialogOptions::AnyFile: + case QFileDialogOptions::ExistingFile: + case QFileDialogOptions::ExistingFiles: + return true; + default: + // Folders can't be imported + return false; + } + }(); + if (!docTypes.count) { switch (fileDialog->options()->fileMode()) { case QFileDialogOptions::AnyFile: @@ -45,7 +58,7 @@ } } - if (self = [super initForOpeningContentTypes:docTypes]) { + if (self = [super initForOpeningContentTypes:docTypes asCopy:asCopy]) { m_fileDialog = fileDialog; self.modalPresentationStyle = UIModalPresentationFormSheet; self.delegate = self; diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.cpp b/src/plugins/platforms/wasm/qwasmaccessibility.cpp index d25474c9b3a..56a7c466dcd 100644 --- a/src/plugins/platforms/wasm/qwasmaccessibility.cpp +++ b/src/plugins/platforms/wasm/qwasmaccessibility.cpp @@ -377,15 +377,23 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac addEventListener(iface, element, "click"); } break; + case QAccessible::Grouping: case QAccessible::CheckBox: { - // QGroupBox uses both CheckBox, and a group with subwidgets - element = document.call<emscripten::val>("createElement", std::string("input")); - setAttribute(element, "type", "checkbox"); - setAttribute(element, "checked", iface->state().checked); - setProperty(element, "indeterminate", iface->state().checkStateMixed); - addEventListener(iface, element, "change"); - if (iface->childCount() > 0) { - auto checkbox = element; + // Three cases: + // 1) role=CheckBox, childCount() == 0 -> Checkbox + // 2) role=CheckBox, childCount() > 0 -> GroupBox w/checkbox + // 3) role=Grouping -> GroupBox w/label + + emscripten::val checkbox = emscripten::val::undefined(); + if (iface->role() == QAccessible::CheckBox) { + checkbox = document.call<emscripten::val>("createElement", std::string("input")); + setAttribute(checkbox, "type", "checkbox"); + setAttribute(checkbox, "checked", iface->state().checked); + setProperty(checkbox, "indeterminate", iface->state().checkStateMixed); + addEventListener(iface, checkbox, "change"); + } + + if (iface->childCount() > 0 || iface->role() == QAccessible::Grouping) { auto label = document.call<emscripten::val>("createElement", std::string("span")); const std::string id = QString::asprintf("lbid%p", iface).toStdString(); @@ -393,11 +401,16 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac element = document.call<emscripten::val>("createElement", std::string("div")); element.call<void>("appendChild", label); - element.call<void>("appendChild", checkbox); setAttribute(element, "role", "group"); setAttribute(element, "aria-labelledby", id); - addEventListener(iface, checkbox, "focus"); + + if (!checkbox.isUndefined()) { + element.call<void>("appendChild", checkbox); + addEventListener(iface, checkbox, "focus"); + } + } else { + element = checkbox; } } break; @@ -800,19 +813,25 @@ void QWasmAccessibility::handleCheckBoxUpdate(QAccessibleEvent *event) void QWasmAccessibility::handleGroupBoxUpdate(QAccessibleEvent *event) { QAccessibleInterface *iface = event->accessibleInterface(); - const emscripten::val parent = getHtmlElement(iface); - const emscripten::val label = parent["children"][0]; - const emscripten::val checkbox = parent["children"][1]; + + emscripten::val parent = getHtmlElement(iface); + emscripten::val label = parent["children"][0]; + emscripten::val checkbox = emscripten::val::undefined(); + if (iface->role() == QAccessible::CheckBox) + checkbox = parent["children"][1]; switch (event->type()) { case QAccessible::Focus: case QAccessible::NameChanged: { setProperty(label, "innerText", iface->text(QAccessible::Name).toStdString()); - setAttribute(checkbox, "aria-label", iface->text(QAccessible::Name).toStdString()); + if (!checkbox.isUndefined()) + setAttribute(checkbox, "aria-label", iface->text(QAccessible::Name).toStdString()); } break; case QAccessible::StateChanged: { - setAttribute(checkbox, "checked", iface->state().checked); - setProperty(checkbox, "indeterminate", iface->state().checkStateMixed); + if (!checkbox.isUndefined()) { + setAttribute(checkbox, "checked", iface->state().checked); + setProperty(checkbox, "indeterminate", iface->state().checkStateMixed); + } } break; default: qCDebug(lcQpaAccessibility) << "TODO: implement handleCheckBoxUpdate for event" << event->type(); @@ -1309,6 +1328,9 @@ void QWasmAccessibility::handleUpdateByInterfaceRole(QAccessibleEvent *event) case QAccessible::ScrollBar: handleScrollBarUpdate(event); break; + case QAccessible::Grouping: + handleGroupBoxUpdate(event); + break; default: qCDebug(lcQpaAccessibility) << "TODO: implement notifyAccessibilityUpdate for role" << iface->role(); }; diff --git a/src/plugins/styles/modernwindows/qwindows11style.cpp b/src/plugins/styles/modernwindows/qwindows11style.cpp index c8cd7c26f61..f47682ced67 100644 --- a/src/plugins/styles/modernwindows/qwindows11style.cpp +++ b/src/plugins/styles/modernwindows/qwindows11style.cpp @@ -993,7 +993,8 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption const bool isMouseOver = state & State_MouseOver; const bool hasFocus = state & State_HasFocus; - if (isMouseOver && !hasFocus && !highContrastTheme) + const bool isEnabled = state & State_Enabled; + if (isMouseOver && isEnabled && hasFocus && !highContrastTheme) drawRoundedRect(painter, frameRect, Qt::NoPen, winUI3Color(subtleHighlightColor)); } break; @@ -1399,6 +1400,13 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op const qreal offset = (int(rect.height()) % 2 == 0) ? 0.5f : 0.0f; if (isIndeterminate) { +#if QT_CONFIG(animation) + auto anim = d->animation(option->styleObject); + if (!anim) { + auto anim = new QStyleAnimation(option->styleObject); + anim->setFrameRate(QStyleAnimation::SixtyFps); + d->startAnimation(anim); + } constexpr auto loopDurationMSec = 4000; const auto elapsedTime = std::chrono::time_point_cast<std::chrono::milliseconds>( std::chrono::system_clock::now()); @@ -1406,14 +1414,20 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op const auto handleCenter = (elapsed % loopDurationMSec) / float(loopDurationMSec); const auto isLongHandle = (elapsed / loopDurationMSec) % 2 == 0; const auto lengthFactor = (isLongHandle ? 33.0f : 25.0f) / 100.0f; +#else + constexpr auto handleCenter = 0.5f; + constexpr auto lengthFactor = 1; +#endif const auto begin = qMax(handleCenter * (1 + lengthFactor) - lengthFactor, 0.0f); const auto end = qMin(handleCenter * (1 + lengthFactor), 1.0f); const auto barBegin = begin * rect.width(); const auto barEnd = end * rect.width(); rect = QRectF(QPointF(rect.left() + barBegin, rect.top()), QPointF(rect.left() + barEnd, rect.bottom())); - const_cast<QWidget *>(widget)->update(); } else { +#if QT_CONFIG(animation) + d->stopAnimation(option->styleObject); +#endif const auto fillPercentage = (float(baropt->progress - baropt->minimum)) / (float(baropt->maximum - baropt->minimum)); rect.setWidth(rect.width() * fillPercentage); @@ -2715,7 +2729,7 @@ void QWindows11Style::drawLineEditFrame(QPainter *p, const QRectF &rect, const Q : winUI3Color(frameColorLight); drawRoundedRect(p, rect, frameCol, Qt::NoBrush); - if (!isEditable) + if (!isEditable || StyleOptionHelper::isDisabled(o)) return; QPainterStateGuard psg(p); diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index b2cfb27e814..d45515e0ecc 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -4658,7 +4658,14 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op #if QT_CONFIG(scrollarea) if (const QAbstractScrollArea *sa = qobject_cast<const QAbstractScrollArea *>(w)) { const QAbstractScrollAreaPrivate *sap = sa->d_func(); - rule.drawBackground(p, opt->rect, sap->contentsOffset()); + bool callBaseClass = true; + if (rule.hasBackground()) { + if (rule.baseStyleCanDraw()) + baseStyle()->drawPrimitive(pe, opt, p, w); + else + rule.drawBackground(p, opt->rect, sap->contentsOffset()); + callBaseClass = false; + } if (rule.hasBorder()) { QRect brect = rule.borderRect(opt->rect); if (styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, opt, w)) { @@ -4667,7 +4674,10 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op brect = QStyle::visualRect(opt->direction, brect, r); } rule.drawBorder(p, brect); + callBaseClass = false; } + if (!callBaseClass) + return; break; } #endif diff --git a/tests/auto/widgets/kernel/qapplication/CMakeLists.txt b/tests/auto/widgets/kernel/qapplication/CMakeLists.txt index 717daf4bcd2..a4f598f3b74 100644 --- a/tests/auto/widgets/kernel/qapplication/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qapplication/CMakeLists.txt @@ -21,9 +21,10 @@ qt_internal_add_executable(apphelper_widgets Qt::Widgets ) set_target_properties(apphelper_widgets PROPERTIES OUTPUT_NAME apphelper) -set_target_properties(tst_qapplication PROPERTIES - QT_ANDROID_EXTRA_LIBS ${CMAKE_CURRENT_BINARY_DIR}/libmodal_helper_${ANDROID_ABI}.so -) + +set_property(TARGET tst_qapplication PROPERTY QT_ANDROID_EXTRA_LIBS + ${CMAKE_CURRENT_BINARY_DIR}/libdesktopsettingsaware_helper_${ANDROID_ABI}.so + ${CMAKE_CURRENT_BINARY_DIR}/libmodal_helper_${ANDROID_ABI}.so) if(QT_FEATURE_library) qt_internal_add_cmake_library(apphelper_widgets_plugin |
