Compare commits
16 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
082bad2484 | ||
|
|
af0ef1e954 | ||
|
|
67c126dc18 | ||
|
|
2ff34253dc | ||
|
|
045b22d4d6 | ||
|
|
05ee0b98b4 | ||
|
|
07c9cbcba0 | ||
|
|
1646c99cab | ||
|
|
060d33bcdd | ||
|
|
362bc3dbd4 | ||
|
|
0e85496669 | ||
|
|
ed748d94e8 | ||
|
|
fe42bba4fc | ||
|
|
ba0d907174 | ||
|
|
49cf38aa7e | ||
|
|
e21e53a974 |
23 changed files with 903 additions and 26361 deletions
7
.gitignore
vendored
7
.gitignore
vendored
|
|
@ -32,3 +32,10 @@
|
|||
/qtbase-everywhere-src-6.8.0.tar.xz
|
||||
/qtbase-everywhere-src-6.8.1.tar.xz
|
||||
/qtbase-everywhere-src-6.8.2.tar.xz
|
||||
/qtbase-everywhere-src-6.9.0-rc.tar.xz
|
||||
/qtbase-everywhere-src-6.9.0.tar.xz
|
||||
/qtbase-everywhere-src-6.9.1.tar.xz
|
||||
/qtbase-everywhere-src-6.9.2.tar.xz
|
||||
/qtbase-everywhere-src-6.10.0-rc.tar.xz
|
||||
/qtbase-everywhere-src-6.10.0.tar.xz
|
||||
/qtbase-everywhere-src-6.10.1.tar.xz
|
||||
|
|
|
|||
195
qt6-qtbase.spec
195
qt6-qtbase.spec
|
|
@ -41,11 +41,13 @@ BuildRequires: pkgconfig(libsystemd)
|
|||
#global tests 1
|
||||
|
||||
#global unstable 0
|
||||
%global prerelease rc2
|
||||
%if 0%{?unstable}
|
||||
%global prerelease rc
|
||||
%endif
|
||||
|
||||
Name: qt6-qtbase
|
||||
Summary: Qt6 - QtBase components
|
||||
Version: 6.8.2
|
||||
Version: 6.10.1
|
||||
Release: 3%{?dist}
|
||||
|
||||
License: LGPL-3.0-only OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
|
@ -96,21 +98,11 @@ Patch56: qtbase-mysql.patch
|
|||
Patch58: qtbase-libglvnd.patch
|
||||
|
||||
# upstream patches
|
||||
Patch100: qtbase-qtlocale-try-to-survive-being-created-during-application-shut-down.patch
|
||||
Patch101: qtbase-qsystemlocale-bail-out-if-accessed-post-destruction.patch
|
||||
Patch102: qtbase-qlibraryinfo-speedup-checking-if-qt-conf-resource-exists.patch
|
||||
|
||||
## upstream patches from Qt 6.9
|
||||
Patch150: qtbase-extract-emoji-data-from-unicode-files.patch
|
||||
Patch151: qtbase-introduce-emoji-segmenter-to-3rdparty-code.patch
|
||||
Patch152: qtbase-use-emoji-segmenter-to-apply-emoji-fonts-automatically.patch
|
||||
Patch153: qtbase-fix-regression-when-looking-up-fallback-fonts.patch
|
||||
Patch154: qtbase-skip-ad-hoc-handling-of-variation-selector-in-font-merging.patch
|
||||
Patch155: qtbase-fontconfig-dont-register-hardcoded-fonts-as-color-fonts.patch
|
||||
Patch156: qtbase-request-actual-font-family-request-in-final-color-font-fail-safe.patch
|
||||
Patch157: qtbase-fontconfig-fix-detection-of-color-fonts.patch
|
||||
Patch158: qtbase-support-variation-selector-when-emoji-segmenter-is-disabled.patch
|
||||
Patch159: qtbase-treat-variation-selectors-as-ignorable-chars.patch
|
||||
Patch100: qtbase-wayland-convey-preference-for-server-side-decorations.patch
|
||||
Patch101: qtbase-wayland-compress-high-frequency-mouse-events.patch
|
||||
Patch102: qtbase-wayland-optimize-scroll-operations.patch
|
||||
Patch103: qtbase-wayland-enable-event-compression-and-fix-scroll-end-event.patch
|
||||
Patch104: qtbase-wayland-fix-crash-in-qwaylandshmbackingstore-scroll.patch
|
||||
|
||||
# Do not check any files in %%{_qt6_plugindir}/platformthemes/ for requires.
|
||||
# Those themes are there for platform integration. If the required libraries are
|
||||
|
|
@ -181,7 +173,13 @@ BuildRequires: pkgconfig(vulkan)
|
|||
BuildRequires: pkgconfig(egl)
|
||||
BuildRequires: pkgconfig(gbm)
|
||||
BuildRequires: pkgconfig(libglvnd)
|
||||
BuildRequires: pkgconfig(xrender)
|
||||
BuildRequires: pkgconfig(x11)
|
||||
BuildRequires: pkgconfig(wayland-scanner)
|
||||
BuildRequires: pkgconfig(wayland-server)
|
||||
BuildRequires: pkgconfig(wayland-client)
|
||||
BuildRequires: pkgconfig(wayland-cursor)
|
||||
BuildRequires: pkgconfig(wayland-egl)
|
||||
|
||||
%global sqlite 1
|
||||
BuildRequires: pkgconfig(sqlite3) >= 3.7
|
||||
|
|
@ -321,7 +319,6 @@ Requires: %{name}%{?_isa} = %{version}-%{release}
|
|||
Summary: Qt6 GUI-related libraries
|
||||
Requires: %{name}%{?_isa} = %{version}-%{release}
|
||||
Recommends: mesa-dri-drivers%{?_isa}
|
||||
Recommends: qt6-qtwayland%{?_isa}
|
||||
# Required for some locales: https://pagure.io/fedora-kde/SIG/issue/311
|
||||
Recommends: qt6-qttranslations
|
||||
Obsoletes: adwaita-qt6 <= 1.4.2
|
||||
|
|
@ -443,7 +440,7 @@ translationdir=%{_qt6_translationdir}
|
|||
|
||||
Name: Qt6
|
||||
Description: Qt6 Configuration
|
||||
Version: 6.8.2
|
||||
Version: 6.10.1
|
||||
EOF
|
||||
|
||||
# rpm macros
|
||||
|
|
@ -514,7 +511,10 @@ rm -r %{buildroot}%{_qt6_libdir}/cmake/Qt6ExamplesAssetDownloaderPrivate
|
|||
rm -r %{buildroot}%{_qt6_headerdir}/QtExamplesAssetDownloader
|
||||
rm %{buildroot}%{_qt6_descriptionsdir}/ExamplesAssetDownloaderPrivate.json
|
||||
rm %{buildroot}%{_qt6_libdir}/libQt6ExamplesAssetDownloader.*
|
||||
rm %{buildroot}%{_qt6_libdir}/qt6/metatypes/qt6examplesassetdownloaderprivate_*_metatypes.json
|
||||
rm %{buildroot}%{_qt6_libdir}/qt6/metatypes/qt6examplesassetdownloaderprivate_metatypes.json
|
||||
|
||||
# These shouldn't be probably installed
|
||||
rm -r %{buildroot}%{_qt6_libdir}/cmake/Qt6/3rdparty/extra-cmake-modules/*.patch
|
||||
|
||||
# This is only for Apple platforms and has a python2 dep
|
||||
rm -r %{buildroot}%{_qt6_mkspecsdir}/features/uikit
|
||||
|
|
@ -609,6 +609,11 @@ make check -k ||:
|
|||
%dir %{_qt6_libdir}/cmake/Qt6PrintSupport
|
||||
%dir %{_qt6_libdir}/cmake/Qt6Sql
|
||||
%dir %{_qt6_libdir}/cmake/Qt6Test
|
||||
%dir %{_qt6_libdir}/cmake/Qt6WaylandClient/
|
||||
%dir %{_qt6_libdir}/cmake/Qt6WaylandClientPrivate
|
||||
%dir %{_qt6_libdir}/cmake/Qt6WaylandGlobalPrivate/
|
||||
%dir %{_qt6_libdir}/cmake/Qt6WaylandScannerTools/
|
||||
%dir %{_qt6_libdir}/cmake/Qt6WlShellIntegrationPrivate/
|
||||
%dir %{_qt6_libdir}/cmake/Qt6Widgets
|
||||
%dir %{_qt6_libdir}/cmake/Qt6WidgetsTools
|
||||
%dir %{_qt6_libdir}/cmake/Qt6Xml
|
||||
|
|
@ -645,6 +650,7 @@ make check -k ||:
|
|||
%{_qt6_libexecdir}/qvkgen
|
||||
%{_qt6_libexecdir}/rcc
|
||||
%{_qt6_libexecdir}/uic
|
||||
%{_qt6_libexecdir}/qtwaylandscanner
|
||||
%{_qt6_headerdir}/QtConcurrent/
|
||||
%{_qt6_headerdir}/QtCore/
|
||||
%{_qt6_headerdir}/QtDBus/
|
||||
|
|
@ -655,6 +661,9 @@ make check -k ||:
|
|||
%{_qt6_headerdir}/QtPrintSupport/
|
||||
%{_qt6_headerdir}/QtSql/
|
||||
%{_qt6_headerdir}/QtTest/
|
||||
%{_qt6_headerdir}/QtWaylandClient/
|
||||
%{_qt6_headerdir}/QtWaylandGlobal/
|
||||
%{_qt6_headerdir}/QtWlShellIntegration/
|
||||
%{_qt6_headerdir}/QtWidgets/
|
||||
%{_qt6_headerdir}/QtXcb/
|
||||
%{_qt6_headerdir}/QtXml/
|
||||
|
|
@ -678,14 +687,19 @@ make check -k ||:
|
|||
%{_qt6_libdir}/libQt6Sql.so
|
||||
%{_qt6_libdir}/libQt6Test.prl
|
||||
%{_qt6_libdir}/libQt6Test.so
|
||||
%{_qt6_libdir}/libQt6WaylandClient.so
|
||||
%{_qt6_libdir}/libQt6WlShellIntegration.so
|
||||
%{_qt6_libdir}/libQt6WaylandClient.prl
|
||||
%{_qt6_libdir}/libQt6WlShellIntegration.prl
|
||||
%{_qt6_libdir}/libQt6Widgets.prl
|
||||
%{_qt6_libdir}/libQt6Widgets.so
|
||||
%{_qt6_libdir}/libQt6XcbQpa.prl
|
||||
%{_qt6_libdir}/libQt6XcbQpa.so
|
||||
%{_qt6_libdir}/libQt6XcbQpa.so
|
||||
%{_qt6_libdir}/libQt6Xml.prl
|
||||
%{_qt6_libdir}/libQt6Xml.so
|
||||
%{_qt6_libdir}/cmake/Qt6/3rdparty/extra-cmake-modules/REUSE.toml
|
||||
%{_qt6_libdir}/cmake/Qt6/3rdparty/kwin/REUSE.toml
|
||||
%{_qt6_libdir}/cmake/Qt6/*.in
|
||||
%{_qt6_libdir}/cmake/Qt6/*.h.in
|
||||
%{_qt6_libdir}/cmake/Qt6/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6/*.cmake.in
|
||||
|
|
@ -727,6 +741,11 @@ make check -k ||:
|
|||
%{_qt6_libdir}/cmake/Qt6Sql/Qt6Sql*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6Sql/Qt6QSQLiteDriverPlugin*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6Test/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6WaylandClient/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6WaylandClientPrivate/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6WaylandGlobalPrivate/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6WaylandScannerTools/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6WlShellIntegrationPrivate/
|
||||
%{_qt6_libdir}/cmake/Qt6Widgets/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6WidgetsTools/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6Xml/*.cmake
|
||||
|
|
@ -740,20 +759,23 @@ make check -k ||:
|
|||
%{_qt6_descriptionsdir}/PrintSupport.json
|
||||
%{_qt6_descriptionsdir}/Sql.json
|
||||
%{_qt6_descriptionsdir}/Test.json
|
||||
%{_qt6_descriptionsdir}/WaylandClient.json
|
||||
%{_qt6_descriptionsdir}/WaylandGlobalPrivate.json
|
||||
%{_qt6_descriptionsdir}/WlShellIntegrationPrivate.json
|
||||
%{_qt6_descriptionsdir}/Widgets.json
|
||||
%{_qt6_descriptionsdir}/Xml.json
|
||||
%{_qt6_metatypesdir}/qt6concurrent_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6core_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6dbus_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6gui_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6network_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6opengl_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6openglwidgets_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6printsupport_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6sql_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6test_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6widgets_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6xml_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6concurrent_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6core_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6dbus_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6gui_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6network_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6opengl_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6openglwidgets_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6printsupport_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6sql_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6test_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6widgets_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6xml_metatypes.json
|
||||
%{_qt6_libdir}/pkgconfig/*.pc
|
||||
%{_qt6_mkspecsdir}/*
|
||||
## private-devel globs
|
||||
|
|
@ -763,10 +785,34 @@ make check -k ||:
|
|||
%{_qt6_headerdir}/QtEglFSDeviceIntegration
|
||||
%{_qt6_headerdir}/QtEglFsKmsGbmSupport
|
||||
%{_qt6_headerdir}/QtEglFsKmsSupport
|
||||
%dir %{_qt6_libdir}/cmake/Qt6CorePrivate
|
||||
%dir %{_qt6_libdir}/cmake/Qt6DBusPrivate
|
||||
%dir %{_qt6_libdir}/cmake/Qt6GuiPrivate
|
||||
%dir %{_qt6_libdir}/cmake/Qt6NetworkPrivate
|
||||
%dir %{_qt6_libdir}/cmake/Qt6OpenGLPrivate
|
||||
%dir %{_qt6_libdir}/cmake/Qt6PrintSupportPrivate
|
||||
%dir %{_qt6_libdir}/cmake/Qt6SqlPrivate
|
||||
%dir %{_qt6_libdir}/cmake/Qt6TestInternalsPrivate
|
||||
%dir %{_qt6_libdir}/cmake/Qt6TestInternalsPrivate/3rdparty/cmake
|
||||
%dir %{_qt6_libdir}/cmake/Qt6TestPrivate
|
||||
%dir %{_qt6_libdir}/cmake/Qt6WidgetsPrivate
|
||||
%dir %{_qt6_libdir}/cmake/Qt6XmlPrivate
|
||||
%dir %{_qt6_libdir}/cmake/Qt6EglFSDeviceIntegrationPrivate
|
||||
%dir %{_qt6_libdir}/cmake/Qt6EglFsKmsGbmSupportPrivate
|
||||
%dir %{_qt6_libdir}/cmake/Qt6EglFsKmsSupportPrivate
|
||||
%dir %{_qt6_libdir}/cmake/Qt6XcbQpaPrivate
|
||||
%{_qt6_libdir}/cmake/Qt6CorePrivate/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6DBusPrivate/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6GuiPrivate/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6NetworkPrivate/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6OpenGLPrivate/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6PrintSupportPrivate/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6SqlPrivate/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6TestInternalsPrivate/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6TestInternalsPrivate/3rdparty/cmake/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6TestPrivate/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6WidgetsPrivate/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6XmlPrivate/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6EglFSDeviceIntegrationPrivate/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6EglFsKmsGbmSupportPrivate/*.cmake
|
||||
%{_qt6_libdir}/cmake/Qt6EglFsKmsSupportPrivate/*.cmake
|
||||
|
|
@ -783,11 +829,14 @@ make check -k ||:
|
|||
%{_qt6_descriptionsdir}/EglFsKmsGbmSupportPrivate.json
|
||||
%{_qt6_descriptionsdir}/EglFsKmsSupportPrivate.json
|
||||
%{_qt6_descriptionsdir}/XcbQpaPrivate.json
|
||||
%{_qt6_metatypesdir}/qt6eglfsdeviceintegrationprivate_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6eglfskmsgbmsupportprivate_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6eglfskmssupportprivate_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6xcbqpaprivate_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6eglfsdeviceintegrationprivate_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6eglfskmsgbmsupportprivate_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6eglfskmssupportprivate_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6xcbqpaprivate_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6waylandclient_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6wlshellintegrationprivate_metatypes.json
|
||||
%{_qt6_headerdir}/*/%{qt_version}/
|
||||
%{_qt6_descriptionsdir}/TestInternalsPrivate.json
|
||||
|
||||
%files static
|
||||
%dir %{_qt6_libdir}/cmake/Qt6ExampleIconsPrivate
|
||||
|
|
@ -798,35 +847,35 @@ make check -k ||:
|
|||
%{_qt6_descriptionsdir}/ExampleIconsPrivate.json
|
||||
%dir %{_qt6_archdatadir}/objects-*
|
||||
%{_qt6_archdatadir}/objects-*/ExampleIconsPrivate_resources_1/
|
||||
%{_qt6_metatypesdir}/qt6exampleiconsprivate_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6exampleiconsprivate_metatypes.json
|
||||
%dir %{_qt6_libdir}/cmake/Qt6DeviceDiscoverySupportPrivate
|
||||
%{_qt6_libdir}/cmake/Qt6DeviceDiscoverySupportPrivate/*.cmake
|
||||
%{_qt6_headerdir}/QtDeviceDiscoverySupport
|
||||
%{_qt6_libdir}/libQt6DeviceDiscoverySupport.*a
|
||||
%{_qt6_libdir}/libQt6DeviceDiscoverySupport.prl
|
||||
%{_qt6_descriptionsdir}/DeviceDiscoverySupportPrivate.json
|
||||
%{_qt6_metatypesdir}/qt6devicediscoverysupportprivate_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6devicediscoverysupportprivate_metatypes.json
|
||||
%dir %{_qt6_libdir}/cmake/Qt6FbSupportPrivate
|
||||
%{_qt6_libdir}/cmake/Qt6FbSupportPrivate/*.cmake
|
||||
%{_qt6_headerdir}/QtFbSupport
|
||||
%{_qt6_libdir}/libQt6FbSupport.*a
|
||||
%{_qt6_libdir}/libQt6FbSupport.prl
|
||||
%{_qt6_descriptionsdir}/FbSupportPrivate.json
|
||||
%{_qt6_metatypesdir}/qt6fbsupportprivate_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6fbsupportprivate_metatypes.json
|
||||
%dir %{_qt6_libdir}/cmake/Qt6InputSupportPrivate
|
||||
%{_qt6_libdir}/cmake/Qt6InputSupportPrivate/*.cmake
|
||||
%{_qt6_headerdir}/QtInputSupport
|
||||
%{_qt6_libdir}/libQt6InputSupport.*a
|
||||
%{_qt6_libdir}/libQt6InputSupport.prl
|
||||
%{_qt6_descriptionsdir}/InputSupportPrivate.json
|
||||
%{_qt6_metatypesdir}/qt6inputsupportprivate_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6inputsupportprivate_metatypes.json
|
||||
%dir %{_qt6_libdir}/cmake/Qt6KmsSupportPrivate
|
||||
%{_qt6_libdir}/cmake/Qt6KmsSupportPrivate/*.cmake
|
||||
%{_qt6_headerdir}/QtKmsSupport
|
||||
%{_qt6_libdir}/libQt6KmsSupport.*a
|
||||
%{_qt6_libdir}/libQt6KmsSupport.prl
|
||||
%{_qt6_descriptionsdir}/KmsSupportPrivate.json
|
||||
%{_qt6_metatypesdir}/qt6kmssupportprivate_*_metatypes.json
|
||||
%{_qt6_metatypesdir}/qt6kmssupportprivate_metatypes.json
|
||||
|
||||
%if 0%{?examples}
|
||||
%files examples
|
||||
|
|
@ -861,6 +910,8 @@ make check -k ||:
|
|||
%{_qt6_libdir}/libQt6OpenGL.so.6*
|
||||
%{_qt6_libdir}/libQt6OpenGLWidgets.so.6*
|
||||
%{_qt6_libdir}/libQt6PrintSupport.so.6*
|
||||
%{_qt6_libdir}/libQt6WaylandClient.so.6*
|
||||
%{_qt6_libdir}/libQt6WlShellIntegration.so.6*
|
||||
%{_qt6_libdir}/libQt6Widgets.so.6*
|
||||
%{_qt6_libdir}/libQt6XcbQpa.so.6*
|
||||
# Generic
|
||||
|
|
@ -899,17 +950,71 @@ make check -k ||:
|
|||
%{_qt6_plugindir}/platforms/libqlinuxfb.so
|
||||
%{_qt6_plugindir}/platforms/libqminimal.so
|
||||
%{_qt6_plugindir}/platforms/libqoffscreen.so
|
||||
%{_qt6_plugindir}/platforms/libqxcb.so
|
||||
%{_qt6_plugindir}/platforms/libqvnc.so
|
||||
%{_qt6_plugindir}/platforms/libqvkkhrdisplay.so
|
||||
%{_qt6_plugindir}/platforms/libqwayland.so
|
||||
%{_qt6_plugindir}/platforms/libqxcb.so
|
||||
%{_qt6_plugindir}/xcbglintegrations/libqxcb-glx-integration.so
|
||||
%{_qt6_plugindir}/printsupport/libcupsprintersupport.so
|
||||
# Platformthemes
|
||||
%{_qt6_plugindir}/platformthemes/libqxdgdesktopportal.so
|
||||
%{_qt6_plugindir}/platformthemes/libqgtk3.so
|
||||
|
||||
# Wayland plugins and protocols
|
||||
%{_qt6_plugindir}/wayland-decoration-client/
|
||||
%{_qt6_plugindir}/wayland-graphics-integration-client
|
||||
%{_qt6_plugindir}/wayland-shell-integration
|
||||
%{_qt6_datadir}/wayland/extensions/
|
||||
%{_qt6_datadir}/wayland/protocols/
|
||||
|
||||
%changelog
|
||||
* Mon Dec 22 2025 Jan Grulich <jgrulich@redhat.com> - 6.10.1-3
|
||||
- Fix crash in QWaylandShmBackingStore::scroll()
|
||||
|
||||
* Mon Dec 08 2025 Jan Grulich <jgrulich@redhat.com> - 6.10.1-2
|
||||
- Re-add wayland fixes for mouse scrolling
|
||||
|
||||
* Thu Nov 20 2025 Jan Grulich <jgrulich@redhat.com> - 6.10.1-1
|
||||
- 6.10.1
|
||||
|
||||
* Mon Nov 10 2025 Jan Grulich <jgrulich@redhat.com> - 6.10.0-3
|
||||
- Backport wayland fixes for mouse scrolling
|
||||
|
||||
* Wed Oct 29 2025 Jan Grulich <jgrulich@redhat.com> - 6.10.0-2
|
||||
- Backport: Wayland - convey preference for server side decorations
|
||||
|
||||
* Tue Oct 07 2025 Jan Grulich <jgrulich@redhat.com> - 6.10.0-1
|
||||
- 6.10.0
|
||||
|
||||
* Tue Sep 30 2025 Gwyn Ciesla <gwync@protonmail.com> - 6.10.0~rc-2
|
||||
- Firebird 5 rebuild
|
||||
|
||||
* Thu Sep 25 2025 Jan Grulich <jgrulich@redhat.com> - 6.10.0~rc-1
|
||||
- 6.10.0 RC
|
||||
|
||||
* Thu Aug 28 2025 Jan Grulich <jgrulich@redhat.com> - 6.9.2-1
|
||||
- 6.9.2
|
||||
|
||||
* Tue Aug 05 2025 František Zatloukal <fzatlouk@redhat.com> - 6.9.1-4
|
||||
- Rebuilt for icu 77.1
|
||||
|
||||
* Mon Jul 28 2025 Adam Williamson <awilliam@redhat.com> - 6.9.1-3
|
||||
- Adjust for https://fedoraproject.org/wiki/Changes/dropingOfCertPemFile removals
|
||||
|
||||
* Fri Jul 25 2025 Fedora Release Engineering <releng@fedoraproject.org> - 6.9.1-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild
|
||||
|
||||
* Mon Jun 02 2025 Jan Grulich <jgrulich@redhat.com> - 6.9.1-1
|
||||
- 6.9.1
|
||||
|
||||
* Mon Apr 28 2025 Jan Grulich <jgrulich@redhat.com> - 6.9.0-2
|
||||
- Fix possible crash in FontConfig database
|
||||
|
||||
* Wed Apr 02 2025 Jan Grulich <jgrulich@redhat.com> - 6.9.0-1
|
||||
- 6.9.0
|
||||
|
||||
* Fri Mar 21 2025 Jan Grulich <jgrulich@redhat.com> - 6.9.0-1
|
||||
- 6.9.0 RC
|
||||
|
||||
* Thu Feb 13 2025 Jan Grulich <jgrulich@redhat.com> - 6.8.2-3
|
||||
- Fix rendering of combined emojis
|
||||
|
||||
|
|
@ -1094,7 +1199,7 @@ make check -k ||:
|
|||
* Fri Apr 7 2023 Marie Loise Nolden <loise@kde.org> - 6.5.0-2
|
||||
- fix xcb plugin with new dependency xcb-cursor instead of Xcursor
|
||||
introduction with qt 6.5, add firebird sql plugin cleanly, clean up spec file
|
||||
|
||||
|
||||
* Mon Apr 03 2023 Jan Grulich <jgrulich@redhat.com> - 6.5.0-1
|
||||
- 6.5.0
|
||||
|
||||
|
|
|
|||
|
|
@ -1,85 +0,0 @@
|
|||
diff --git a/src/gui/text/unix/qfontconfigdatabase.cpp b/src/gui/text/unix/qfontconfigdatabase.cpp
|
||||
index 474644b8..f61e6e83 100644
|
||||
--- a/src/gui/text/unix/qfontconfigdatabase.cpp
|
||||
+++ b/src/gui/text/unix/qfontconfigdatabase.cpp
|
||||
@@ -592,6 +592,7 @@ void QFontconfigDatabase::populateFontDatabase()
|
||||
++f;
|
||||
}
|
||||
|
||||
+ cacheEmojiFontFamily();
|
||||
//QPA has very lazy population of the font db. We want it to be initialized when
|
||||
//QApplication is constructed, so that the population procedure can do something like this to
|
||||
//set the default font
|
||||
@@ -735,6 +736,9 @@ QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont
|
||||
if (!pattern)
|
||||
return fallbackFamilies;
|
||||
|
||||
+ if (!m_cacheEmojiFontFamily.isEmpty())
|
||||
+ fallbackFamilies << m_cacheEmojiFontFamily;
|
||||
+
|
||||
FcValue value;
|
||||
value.type = FcTypeString;
|
||||
const QByteArray cs = family.toUtf8();
|
||||
@@ -1016,4 +1020,47 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef
|
||||
engine->glyphFormat = format;
|
||||
}
|
||||
|
||||
+void QFontconfigDatabase::cacheEmojiFontFamily()
|
||||
+{
|
||||
+ FcPattern *pattern;
|
||||
+ pattern = FcPatternCreate();
|
||||
+
|
||||
+ FcValue value;
|
||||
+ value.type = FcTypeString;
|
||||
+ value.u.s = (const FcChar8 *)"emoji";
|
||||
+ FcPatternAdd(pattern,FC_FAMILY,value,true);
|
||||
+
|
||||
+ FcLangSet *ls = FcLangSetCreate();
|
||||
+ FcLangSetAdd(ls, (const FcChar8*)"und-zsye");
|
||||
+ FcPatternAddLangSet(pattern, FC_LANG, ls);
|
||||
+
|
||||
+ FcConfigSubstitute(nullptr, pattern, FcMatchPattern);
|
||||
+ FcDefaultSubstitute(pattern);
|
||||
+
|
||||
+ FcResult result = FcResultMatch;
|
||||
+ FcFontSet *fontSet = FcFontSort(nullptr,pattern,FcTrue,nullptr,&result);
|
||||
+ FcPatternDestroy(pattern);
|
||||
+
|
||||
+ if (fontSet) {
|
||||
+ for (int i = 0; i < fontSet->nfont; i++) {
|
||||
+ FcChar8 *value = nullptr;
|
||||
+ if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch)
|
||||
+ continue;
|
||||
+
|
||||
+ FcLangSet *rls = nullptr;
|
||||
+ if (FcPatternGetLangSet(fontSet->fonts[i], FC_LANG, 0, &rls) != FcResultMatch)
|
||||
+ continue;
|
||||
+
|
||||
+ if (!FcLangSetContains(rls, ls))
|
||||
+ continue;
|
||||
+
|
||||
+ m_cacheEmojiFontFamily = QString::fromUtf8((const char *)value);
|
||||
+ break;
|
||||
+ }
|
||||
+ FcFontSetDestroy(fontSet);
|
||||
+ }
|
||||
+
|
||||
+ FcLangSetDestroy(ls);
|
||||
+}
|
||||
+
|
||||
QT_END_NAMESPACE
|
||||
diff --git a/src/gui/text/unix/qfontconfigdatabase_p.h b/src/gui/text/unix/qfontconfigdatabase_p.h
|
||||
index cf15306e..90b94087 100644
|
||||
--- a/src/gui/text/unix/qfontconfigdatabase_p.h
|
||||
+++ b/src/gui/text/unix/qfontconfigdatabase_p.h
|
||||
@@ -37,7 +37,10 @@ public:
|
||||
QFont defaultFont() const override;
|
||||
|
||||
private:
|
||||
+ void cacheEmojiFontFamily();
|
||||
void setupFontEngine(QFontEngineFT *engine, const QFontDef &fontDef) const;
|
||||
+
|
||||
+ QString m_cacheEmojiFontFamily;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,96 +0,0 @@
|
|||
From 486bbc7a5bc4483ecc2a6b8927543725e3d38722 Mon Sep 17 00:00:00 2001
|
||||
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||
Date: Tue, 26 Nov 2024 14:39:44 +0100
|
||||
Subject: Fix regression when looking up fallback fonts
|
||||
|
||||
This amends 16850709306589a2433c0038605d365a6b6bedad.
|
||||
|
||||
In that change, the final pass for looking up fallback
|
||||
fonts was turned into a lambda so that we could run it
|
||||
an additional time at the very end. However, when making
|
||||
a lambda from the code, some of the logic was accidentally
|
||||
changed.
|
||||
|
||||
Specifically, for multi engines the original code would pass
|
||||
Script_Common instead of the requested script to the match()
|
||||
function, but it would still pass the actual script to
|
||||
loadEngine() as well as store it in the key. In the changed
|
||||
code, Script_Common would be used for all of these when multi
|
||||
was true.
|
||||
|
||||
This change was not intentional and it caused us to fail to
|
||||
load certain fallback fonts, for instance the Bengali font
|
||||
on Windows.
|
||||
|
||||
Fixes: QTBUG-131632
|
||||
Change-Id: Id215ee4dc2851e846be27a3a25a31cad57b8f67d
|
||||
Reviewed-by: Lars Knoll <lars@knoll.priv.no>
|
||||
|
||||
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
|
||||
index 96c2337e..0c2a4b66 100644
|
||||
--- a/src/gui/text/qfontdatabase.cpp
|
||||
+++ b/src/gui/text/qfontdatabase.cpp
|
||||
@@ -2734,17 +2734,23 @@ QFontEngine *QFontDatabasePrivate::findFont(const QFontDef &req,
|
||||
if (script > QChar::Script_Common)
|
||||
fallbacks += QString(); // Find the first font matching the specified script.
|
||||
|
||||
- auto findMatchingFallback = [&](int xscript) {
|
||||
+ auto findMatchingFallback = [&fallbacks,
|
||||
+ &index,
|
||||
+ &multi,
|
||||
+ &fontCache,
|
||||
+ &blackListed,
|
||||
+ &request](int lookupScript, int cacheScript) {
|
||||
+ QFontEngine *engine = nullptr;
|
||||
for (int i = 0; !engine && i < fallbacks.size(); i++) {
|
||||
QFontDef def = request;
|
||||
|
||||
def.families = QStringList(fallbacks.at(i));
|
||||
- QFontCache::Key key(def, xscript, multi ? 1 : 0);
|
||||
+ QFontCache::Key key(def, cacheScript, multi ? 1 : 0);
|
||||
engine = fontCache->findEngine(key);
|
||||
if (!engine) {
|
||||
QtFontDesc desc;
|
||||
do {
|
||||
- index = match(xscript,
|
||||
+ index = match(lookupScript,
|
||||
def,
|
||||
def.families.constFirst(),
|
||||
""_L1,
|
||||
@@ -2755,7 +2761,12 @@ QFontEngine *QFontDatabasePrivate::findFont(const QFontDef &req,
|
||||
QFontDef loadDef = def;
|
||||
if (loadDef.families.isEmpty())
|
||||
loadDef.families = QStringList(desc.family->name);
|
||||
- engine = loadEngine(xscript, loadDef, desc.family, desc.foundry, desc.style, desc.size);
|
||||
+ engine = loadEngine(cacheScript,
|
||||
+ loadDef,
|
||||
+ desc.family,
|
||||
+ desc.foundry,
|
||||
+ desc.style,
|
||||
+ desc.size);
|
||||
if (engine)
|
||||
initFontDef(desc, loadDef, &engine->fontDef, multi);
|
||||
else
|
||||
@@ -2764,15 +2775,20 @@ QFontEngine *QFontDatabasePrivate::findFont(const QFontDef &req,
|
||||
} while (index >= 0 && !engine);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ return engine;
|
||||
};
|
||||
|
||||
- findMatchingFallback(multi && script != QFontDatabasePrivate::Script_Emoji ? QChar::Script_Common: script);
|
||||
+ engine = findMatchingFallback(multi && script != QFontDatabasePrivate::Script_Emoji
|
||||
+ ? QChar::Script_Common
|
||||
+ : script,
|
||||
+ script);
|
||||
|
||||
// If we are looking for a color font and there are no color fonts on the system,
|
||||
// we will end up here, for one final pass. This is a rare occurrence so we accept
|
||||
// and extra pass on the fallbacks for this.
|
||||
if (!engine && script == QFontDatabasePrivate::Script_Emoji)
|
||||
- findMatchingFallback(QChar::Script_Common);
|
||||
+ engine = findMatchingFallback(QChar::Script_Common, script);
|
||||
}
|
||||
|
||||
if (!engine)
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
From 83864f8682da73a062a3ca32b928377dfc333021 Mon Sep 17 00:00:00 2001
|
||||
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||
Date: Wed, 15 Jan 2025 14:52:55 +0100
|
||||
Subject: [PATCH] FontConfig: Don't register hardcoded fonts as color fonts
|
||||
|
||||
This amends 16850709306589a2433c0038605d365a6b6bedad. The patch
|
||||
aimed to pass false for the color font parameter, but got it in
|
||||
the wrong position, so it passed false for the pixel size instead.
|
||||
|
||||
The registerFont() function is a real mess, and it should be cleaned
|
||||
up, but this at least fixes the immediate bug.
|
||||
|
||||
Pick-to: 6.9
|
||||
Task-number: QTBUG-132821
|
||||
Change-Id: Id54989960aa5f86d3c79423d004530bb6a4fa475
|
||||
---
|
||||
|
||||
diff --git a/src/gui/text/unix/qfontconfigdatabase.cpp b/src/gui/text/unix/qfontconfigdatabase.cpp
|
||||
index 7866e341..790316a6 100644
|
||||
--- a/src/gui/text/unix/qfontconfigdatabase.cpp
|
||||
+++ b/src/gui/text/unix/qfontconfigdatabase.cpp
|
||||
@@ -622,9 +622,9 @@ void QFontconfigDatabase::populateFontDatabase()
|
||||
|
||||
while (f->qtname) {
|
||||
QString familyQtName = QString::fromLatin1(f->qtname);
|
||||
- registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleNormal,QFont::Unstretched,true,true,false,0,f->fixed,ws,nullptr);
|
||||
- registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleItalic,QFont::Unstretched,true,true,false,0,f->fixed,ws,nullptr);
|
||||
- registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleOblique,QFont::Unstretched,true,true,false,0,f->fixed,ws,nullptr);
|
||||
+ registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleNormal,QFont::Unstretched,true,true,0,f->fixed,false,ws,nullptr);
|
||||
+ registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleItalic,QFont::Unstretched,true,true,0,f->fixed,false,ws,nullptr);
|
||||
+ registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleOblique,QFont::Unstretched,true,true,0,f->fixed,false,ws,nullptr);
|
||||
++f;
|
||||
}
|
||||
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
From 2c309f71705449607592bb4588bcc56223da897b Mon Sep 17 00:00:00 2001
|
||||
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||
Date: Wed, 15 Jan 2025 15:39:16 +0100
|
||||
Subject: [PATCH] FontConfig: Fix detection of color fonts
|
||||
|
||||
There were two mistakes in the code that intended to detect
|
||||
if a specific font was a color font in the FontConfig database.
|
||||
|
||||
1. The "int n" parameter in FcPatternGet*() is not an array size,
|
||||
but an index, so it should be 0 and not 1.
|
||||
|
||||
2. We need to add FC_COLOR to the list of properties in our pattern
|
||||
when populating the database, otherwise we will just fail to match
|
||||
it and none of the system fonts will be listed as color.
|
||||
|
||||
Pick-to: 6.9
|
||||
Fixes: QTBUG-132377
|
||||
Change-Id: Ib3c112e8a354abacd05679c62283a1f1abfb40ee
|
||||
---
|
||||
|
||||
diff --git a/src/gui/text/unix/qfontconfigdatabase.cpp b/src/gui/text/unix/qfontconfigdatabase.cpp
|
||||
index de6618f..20794ed 100644
|
||||
--- a/src/gui/text/unix/qfontconfigdatabase.cpp
|
||||
+++ b/src/gui/text/unix/qfontconfigdatabase.cpp
|
||||
@@ -478,7 +478,7 @@
|
||||
|
||||
FcBool colorFont = false;
|
||||
#ifdef FC_COLOR
|
||||
- FcPatternGetBool(pattern, FC_COLOR, 1, &colorFont);
|
||||
+ FcPatternGetBool(pattern, FC_COLOR, 0, &colorFont);
|
||||
#endif
|
||||
|
||||
// Note: stretch should really be an int but registerFont incorrectly uses an enum
|
||||
@@ -577,6 +577,9 @@
|
||||
#if FC_VERSION >= 20297
|
||||
FC_CAPABILITY,
|
||||
#endif
|
||||
+#if defined(FC_COLOR)
|
||||
+ FC_COLOR,
|
||||
+#endif
|
||||
(const char *)nullptr
|
||||
};
|
||||
const char **p = properties;
|
||||
|
|
@ -1,568 +0,0 @@
|
|||
From aa7d479be0df3e118580e87f30e061445dfb37e3 Mon Sep 17 00:00:00 2001
|
||||
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||
Date: Fri, 2 Feb 2024 15:45:20 +0100
|
||||
Subject: Introduce emoji-segmenter to 3rdparty code
|
||||
|
||||
This is a parser for emoji sequences developed by Google
|
||||
which is used in multiple other projects for parsing
|
||||
sequences of characters to see if they should be represented
|
||||
as color emojis or as monochrome text.
|
||||
|
||||
[ChangeLog][Third-Party Code] Added the emoji-segmenter to
|
||||
third party code, for supporting complex emoji sequences.
|
||||
This can be configured using the -emojisegmenter option.
|
||||
|
||||
Task-number: QTBUG-111801
|
||||
Change-Id: I7f87b0751415024d29f074d133850027f0003e29
|
||||
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
|
||||
|
||||
diff --git a/config_help.txt b/config_help.txt
|
||||
index deb38c9c2f..09aebf2e65 100644
|
||||
--- a/config_help.txt
|
||||
+++ b/config_help.txt
|
||||
@@ -298,6 +298,7 @@ Gui, printing, widget options:
|
||||
|
||||
-cups ................ Enable CUPS support [auto] (Unix only)
|
||||
|
||||
+ -emojisegmenter ...... Enable complex emoji sequences [yes]
|
||||
-fontconfig .......... Enable Fontconfig support [auto] (Unix only)
|
||||
-freetype ............ Select used FreeType [system/qt/no]
|
||||
-harfbuzz ............ Select used HarfBuzz-NG [system/qt/no]
|
||||
diff --git a/src/3rdparty/emoji-segmenter/CONTRIBUTING.md b/src/3rdparty/emoji-segmenter/CONTRIBUTING.md
|
||||
new file mode 100644
|
||||
index 0000000000..db177d4ac7
|
||||
--- /dev/null
|
||||
+++ b/src/3rdparty/emoji-segmenter/CONTRIBUTING.md
|
||||
@@ -0,0 +1,28 @@
|
||||
+# How to Contribute
|
||||
+
|
||||
+We'd love to accept your patches and contributions to this project. There are
|
||||
+just a few small guidelines you need to follow.
|
||||
+
|
||||
+## Contributor License Agreement
|
||||
+
|
||||
+Contributions to this project must be accompanied by a Contributor License
|
||||
+Agreement. You (or your employer) retain the copyright to your contribution;
|
||||
+this simply gives us permission to use and redistribute your contributions as
|
||||
+part of the project. Head over to <https://cla.developers.google.com/> to see
|
||||
+your current agreements on file or to sign a new one.
|
||||
+
|
||||
+You generally only need to submit a CLA once, so if you've already submitted one
|
||||
+(even if it was for a different project), you probably don't need to do it
|
||||
+again.
|
||||
+
|
||||
+## Code reviews
|
||||
+
|
||||
+All submissions, including submissions by project members, require review. We
|
||||
+use GitHub pull requests for this purpose. Consult
|
||||
+[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
|
||||
+information on using pull requests.
|
||||
+
|
||||
+## Community Guidelines
|
||||
+
|
||||
+This project follows
|
||||
+[Google's Open Source Community Guidelines](https://opensource.google.com/conduct/).
|
||||
diff --git a/src/3rdparty/emoji-segmenter/NEWS b/src/3rdparty/emoji-segmenter/NEWS
|
||||
new file mode 100644
|
||||
index 0000000000..3fd07f1ce2
|
||||
--- /dev/null
|
||||
+++ b/src/3rdparty/emoji-segmenter/NEWS
|
||||
@@ -0,0 +1,28 @@
|
||||
+Overview of changes leading to 0.4.0
|
||||
+Friday, November 15, 2024
|
||||
+====================================
|
||||
+
|
||||
+* Add `make size` targe to
|
||||
+ determine binary size.
|
||||
+* Set has_vs for
|
||||
+ emoji_keycap_sequence
|
||||
+
|
||||
+Overview of changes leading to 0.3.0
|
||||
+Tuesday, September 5, 2024
|
||||
+====================================
|
||||
+
|
||||
+* Add segmentation for variation
|
||||
+ selector pairs, VS15 and VS16,
|
||||
+ needed for font-variant-emoji.
|
||||
+
|
||||
+Overview of changes leading to 0.2.0
|
||||
+Tuesday, Februar 20, 2024
|
||||
+====================================
|
||||
+
|
||||
+* Change Ragel mode to -F1
|
||||
+
|
||||
+Overview of changes leading to 0.1.0
|
||||
+Tuesday, January 29, 2019
|
||||
+====================================
|
||||
+
|
||||
+* Initial release
|
||||
diff --git a/src/3rdparty/emoji-segmenter/README.md b/src/3rdparty/emoji-segmenter/README.md
|
||||
new file mode 100644
|
||||
index 0000000000..571a1a4515
|
||||
--- /dev/null
|
||||
+++ b/src/3rdparty/emoji-segmenter/README.md
|
||||
@@ -0,0 +1,103 @@
|
||||
+Emoji Segmenter
|
||||
+===
|
||||
+
|
||||
+This repository contains a Ragel grammar and generated C code for segmenting
|
||||
+runs of text into text-presentation and emoji-presentation runs. It is currently
|
||||
+used in projects such as Chromium and Pango for deciding which preferred
|
||||
+presentation, color or text, a run of text should have.
|
||||
+
|
||||
+The goal is to stay very close to the grammar definitions in [Unicode Technical
|
||||
+Standard #51](http://www.unicode.org/reports/tr51/).
|
||||
+
|
||||
+API
|
||||
+===
|
||||
+
|
||||
+By including the `emoji_presentation_scanner.c` file, you will be able to call
|
||||
+the following API
|
||||
+
|
||||
+```
|
||||
+scan_emoji_presentation (emoji_text_iter_t p,
|
||||
+ const emoji_text_iter_t pe,
|
||||
+ bool* is_emoji,
|
||||
+ bool* has_vs)
|
||||
+```
|
||||
+
|
||||
+This API call will scan `emoji_text_iter_t p` for the next grammar-token and
|
||||
+return an iterator that points to the end of the next token. An end iterator
|
||||
+needs be specified as `pe` so that the scanner can compare against this and
|
||||
+knows where to stop. In the reference parameter `is_emoji` it returns whether
|
||||
+this token has emoji-presentation text-presentation, `has_vs` is set to true
|
||||
+if the token contains a variation selector.
|
||||
+
|
||||
+A grammar token is either a combination of an emoji plus variation selector 15
|
||||
+for text presentation, an emoji presentation sequence (emoji + VS16), an emoji
|
||||
+presentation emoji or emoji sequence, or a single text presentation character.
|
||||
+
|
||||
+`emoji_text_iter_t` is an iterator type over a buffer of the character classes
|
||||
+that are defined at the beginning of the the Ragel file, e.g. `EMOJI`,
|
||||
+`EMOJI_TEXT_PRESENTATION`, `REGIONAL_INDICATOR`, `KEYCAP_BASE`, etc.
|
||||
+
|
||||
+By typedef'ing `emoji_text_iter_t` to your own iterator type, you can implement
|
||||
+an adapter class that iterates over an input text buffer in any encoding, and on
|
||||
+dereferencing returns the correct Ragel class by implementing something similar
|
||||
+to the following Unicode character class to Ragel class mapping, example taken
|
||||
+from Chromium:
|
||||
+
|
||||
+```
|
||||
+char EmojiSegmentationCategory(UChar32 codepoint) {
|
||||
+ // Specific ones first.
|
||||
+ if (codepoint == kCombiningEnclosingKeycapCharacter)
|
||||
+ return COMBINING_ENCLOSING_KEYCAP;
|
||||
+ if (codepoint == kCombiningEnclosingCircleBackslashCharacter)
|
||||
+ return COMBINING_ENCLOSING_CIRCLE_BACKSLASH;
|
||||
+ if (codepoint == kZeroWidthJoinerCharacter)
|
||||
+ return ZWJ;
|
||||
+ if (codepoint == kVariationSelector15Character)
|
||||
+ return VS15;
|
||||
+ if (codepoint == kVariationSelector16Character)
|
||||
+ return VS16;
|
||||
+ if (codepoint == 0x1F3F4)
|
||||
+ return TAG_BASE;
|
||||
+ if ((codepoint >= 0xE0030 && codepoint <= 0xE0039) ||
|
||||
+ (codepoint >= 0xE0061 && codepoint <= 0xE007A))
|
||||
+ return TAG_SEQUENCE;
|
||||
+ if (codepoint == 0xE007F)
|
||||
+ return TAG_TERM;
|
||||
+ if (Character::IsEmojiModifierBase(codepoint))
|
||||
+ return EMOJI_MODIFIER_BASE;
|
||||
+ if (Character::IsModifier(codepoint))
|
||||
+ return EMOJI_MODIFIER;
|
||||
+ if (Character::IsRegionalIndicator(codepoint))
|
||||
+ return REGIONAL_INDICATOR;
|
||||
+ if (Character::IsEmojiKeycapBase(codepoint))
|
||||
+ return KEYCAP_BASE;
|
||||
+
|
||||
+ if (Character::IsEmojiEmojiDefault(codepoint))
|
||||
+ return EMOJI_EMOJI_PRESENTATION;
|
||||
+ if (Character::IsEmojiTextDefault(codepoint))
|
||||
+ return EMOJI_TEXT_PRESENTATION;
|
||||
+ if (Character::IsEmoji(codepoint))
|
||||
+ return EMOJI;
|
||||
+
|
||||
+ // Ragel state machine will interpret unknown category as "any".
|
||||
+ return kMaxEmojiScannerCategory;
|
||||
+}
|
||||
+```
|
||||
+
|
||||
+Update/Build requisites
|
||||
+===
|
||||
+
|
||||
+You need to have ragel installed if you want to modify the grammar and generate a new C file as output.
|
||||
+
|
||||
+`apt-get install ragel`
|
||||
+
|
||||
+then run
|
||||
+
|
||||
+`make`
|
||||
+
|
||||
+to update the `emoji_presentation_scanner.c` and `emoji_presentation_scanner_vs.c` output C source file.
|
||||
+
|
||||
+Contributing
|
||||
+===
|
||||
+
|
||||
+See the CONTRIBUTING.md file for how to contribute.
|
||||
diff --git a/src/3rdparty/emoji-segmenter/REUSE.toml b/src/3rdparty/emoji-segmenter/REUSE.toml
|
||||
new file mode 100644
|
||||
index 0000000000..53d2dc47c7
|
||||
--- /dev/null
|
||||
+++ b/src/3rdparty/emoji-segmenter/REUSE.toml
|
||||
@@ -0,0 +1,7 @@
|
||||
+version = 1
|
||||
+
|
||||
+[[annotations]]
|
||||
+path = ["**"]
|
||||
+precedence = "closest"
|
||||
+SPDX-FileCopyrightText = "Copyright 2019 Google LLC"
|
||||
+SPDX-License-Identifier = "Apache-2.0"
|
||||
diff --git a/src/3rdparty/emoji-segmenter/emoji_presentation_scanner.c b/src/3rdparty/emoji-segmenter/emoji_presentation_scanner.c
|
||||
new file mode 100644
|
||||
index 0000000000..00b7700a9a
|
||||
--- /dev/null
|
||||
+++ b/src/3rdparty/emoji-segmenter/emoji_presentation_scanner.c
|
||||
@@ -0,0 +1,251 @@
|
||||
+
|
||||
+#line 1 "emoji_presentation_scanner.rl"
|
||||
+/* Copyright 2019 Google LLC
|
||||
+ *
|
||||
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
+ * you may not use this file except in compliance with the License.
|
||||
+ * You may obtain a copy of the License at
|
||||
+ *
|
||||
+ * https://www.apache.org/licenses/LICENSE-2.0
|
||||
+ *
|
||||
+ * Unless required by applicable law or agreed to in writing, software
|
||||
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
+ * See the License for the specific language governing permissions and
|
||||
+ * limitations under the License.
|
||||
+ */
|
||||
+
|
||||
+#include <stdbool.h>
|
||||
+
|
||||
+#ifndef EMOJI_LINKAGE
|
||||
+#define EMOJI_LINKAGE static
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
+#line 23 "emoji_presentation_scanner.c"
|
||||
+static const unsigned char _emoji_presentation_trans_keys[] = {
|
||||
+ 0u, 13u, 14u, 15u, 0u, 13u, 9u, 12u, 10u, 12u, 10u, 10u, 4u, 12u, 4u, 12u,
|
||||
+ 6u, 6u, 9u, 12u, 8u, 8u, 8u, 10u, 9u, 14u, 0
|
||||
+};
|
||||
+
|
||||
+static const char _emoji_presentation_key_spans[] = {
|
||||
+ 14, 2, 14, 4, 3, 1, 9, 9,
|
||||
+ 1, 4, 1, 3, 6
|
||||
+};
|
||||
+
|
||||
+static const char _emoji_presentation_index_offsets[] = {
|
||||
+ 0, 15, 18, 33, 38, 42, 44, 54,
|
||||
+ 64, 66, 71, 73, 77
|
||||
+};
|
||||
+
|
||||
+static const char _emoji_presentation_indicies[] = {
|
||||
+ 1, 1, 1, 2, 0, 0, 0, 1,
|
||||
+ 0, 0, 0, 0, 0, 1, 0, 4,
|
||||
+ 5, 3, 6, 6, 7, 8, 9, 9,
|
||||
+ 10, 11, 9, 9, 9, 9, 9, 12,
|
||||
+ 9, 5, 13, 14, 15, 0, 13, 16,
|
||||
+ 17, 16, 13, 0, 17, 16, 16, 16,
|
||||
+ 16, 16, 13, 16, 17, 16, 17, 16,
|
||||
+ 16, 16, 16, 5, 13, 14, 15, 16,
|
||||
+ 5, 18, 5, 13, 19, 20, 18, 14,
|
||||
+ 21, 23, 22, 13, 22, 5, 13, 14,
|
||||
+ 15, 16, 4, 16, 0
|
||||
+};
|
||||
+
|
||||
+static const char _emoji_presentation_trans_targs[] = {
|
||||
+ 2, 4, 6, 2, 1, 2, 3, 3,
|
||||
+ 7, 2, 8, 9, 12, 0, 2, 5,
|
||||
+ 2, 5, 2, 10, 11, 2, 2, 2
|
||||
+};
|
||||
+
|
||||
+static const char _emoji_presentation_trans_actions[] = {
|
||||
+ 1, 2, 2, 3, 0, 4, 7, 2,
|
||||
+ 2, 8, 0, 7, 2, 0, 9, 10,
|
||||
+ 11, 2, 12, 0, 10, 13, 14, 15
|
||||
+};
|
||||
+
|
||||
+static const char _emoji_presentation_to_state_actions[] = {
|
||||
+ 0, 0, 5, 0, 0, 0, 0, 0,
|
||||
+ 0, 0, 0, 0, 0
|
||||
+};
|
||||
+
|
||||
+static const char _emoji_presentation_from_state_actions[] = {
|
||||
+ 0, 0, 6, 0, 0, 0, 0, 0,
|
||||
+ 0, 0, 0, 0, 0
|
||||
+};
|
||||
+
|
||||
+static const char _emoji_presentation_eof_trans[] = {
|
||||
+ 1, 4, 0, 1, 17, 1, 17, 17,
|
||||
+ 19, 19, 22, 23, 17
|
||||
+};
|
||||
+
|
||||
+static const int emoji_presentation_start = 2;
|
||||
+
|
||||
+static const int emoji_presentation_en_text_and_emoji_run = 2;
|
||||
+
|
||||
+
|
||||
+#line 26 "emoji_presentation_scanner.rl"
|
||||
+
|
||||
+
|
||||
+
|
||||
+#line 100 "emoji_presentation_scanner.rl"
|
||||
+
|
||||
+
|
||||
+EMOJI_LINKAGE emoji_text_iter_t
|
||||
+scan_emoji_presentation (emoji_text_iter_t p,
|
||||
+ const emoji_text_iter_t pe,
|
||||
+ bool* is_emoji,
|
||||
+ bool* has_vs)
|
||||
+{
|
||||
+ emoji_text_iter_t ts;
|
||||
+ emoji_text_iter_t te;
|
||||
+ const emoji_text_iter_t eof = pe;
|
||||
+
|
||||
+ (void)ts;
|
||||
+
|
||||
+ unsigned act;
|
||||
+ int cs;
|
||||
+
|
||||
+
|
||||
+#line 100 "emoji_presentation_scanner.c"
|
||||
+ {
|
||||
+ cs = emoji_presentation_start;
|
||||
+ ts = 0;
|
||||
+ te = 0;
|
||||
+ act = 0;
|
||||
+ }
|
||||
+
|
||||
+#line 106 "emoji_presentation_scanner.c"
|
||||
+ {
|
||||
+ int _slen;
|
||||
+ int _trans;
|
||||
+ const unsigned char *_keys;
|
||||
+ const char *_inds;
|
||||
+ if ( p == pe )
|
||||
+ goto _test_eof;
|
||||
+_resume:
|
||||
+ switch ( _emoji_presentation_from_state_actions[cs] ) {
|
||||
+ case 6:
|
||||
+#line 1 "NONE"
|
||||
+ {ts = p;}
|
||||
+ break;
|
||||
+#line 118 "emoji_presentation_scanner.c"
|
||||
+ }
|
||||
+
|
||||
+ _keys = _emoji_presentation_trans_keys + (cs<<1);
|
||||
+ _inds = _emoji_presentation_indicies + _emoji_presentation_index_offsets[cs];
|
||||
+
|
||||
+ _slen = _emoji_presentation_key_spans[cs];
|
||||
+ _trans = _inds[ _slen > 0 && _keys[0] <=(*p) &&
|
||||
+ (*p) <= _keys[1] ?
|
||||
+ (*p) - _keys[0] : _slen ];
|
||||
+
|
||||
+_eof_trans:
|
||||
+ cs = _emoji_presentation_trans_targs[_trans];
|
||||
+
|
||||
+ if ( _emoji_presentation_trans_actions[_trans] == 0 )
|
||||
+ goto _again;
|
||||
+
|
||||
+ switch ( _emoji_presentation_trans_actions[_trans] ) {
|
||||
+ case 9:
|
||||
+#line 94 "emoji_presentation_scanner.rl"
|
||||
+ {te = p+1;{ *is_emoji = false; *has_vs = true; return te; }}
|
||||
+ break;
|
||||
+ case 15:
|
||||
+#line 95 "emoji_presentation_scanner.rl"
|
||||
+ {te = p+1;{ *is_emoji = true; *has_vs = true; return te; }}
|
||||
+ break;
|
||||
+ case 4:
|
||||
+#line 96 "emoji_presentation_scanner.rl"
|
||||
+ {te = p+1;{ *is_emoji = true; *has_vs = false; return te; }}
|
||||
+ break;
|
||||
+ case 8:
|
||||
+#line 97 "emoji_presentation_scanner.rl"
|
||||
+ {te = p+1;{ *is_emoji = false; *has_vs = false; return te; }}
|
||||
+ break;
|
||||
+ case 13:
|
||||
+#line 94 "emoji_presentation_scanner.rl"
|
||||
+ {te = p;p--;{ *is_emoji = false; *has_vs = true; return te; }}
|
||||
+ break;
|
||||
+ case 14:
|
||||
+#line 95 "emoji_presentation_scanner.rl"
|
||||
+ {te = p;p--;{ *is_emoji = true; *has_vs = true; return te; }}
|
||||
+ break;
|
||||
+ case 11:
|
||||
+#line 96 "emoji_presentation_scanner.rl"
|
||||
+ {te = p;p--;{ *is_emoji = true; *has_vs = false; return te; }}
|
||||
+ break;
|
||||
+ case 12:
|
||||
+#line 97 "emoji_presentation_scanner.rl"
|
||||
+ {te = p;p--;{ *is_emoji = false; *has_vs = false; return te; }}
|
||||
+ break;
|
||||
+ case 3:
|
||||
+#line 96 "emoji_presentation_scanner.rl"
|
||||
+ {{p = ((te))-1;}{ *is_emoji = true; *has_vs = false; return te; }}
|
||||
+ break;
|
||||
+ case 1:
|
||||
+#line 1 "NONE"
|
||||
+ { switch( act ) {
|
||||
+ case 2:
|
||||
+ {{p = ((te))-1;} *is_emoji = true; *has_vs = true; return te; }
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ {{p = ((te))-1;} *is_emoji = true; *has_vs = false; return te; }
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ {{p = ((te))-1;} *is_emoji = false; *has_vs = false; return te; }
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ break;
|
||||
+ case 10:
|
||||
+#line 1 "NONE"
|
||||
+ {te = p+1;}
|
||||
+#line 95 "emoji_presentation_scanner.rl"
|
||||
+ {act = 2;}
|
||||
+ break;
|
||||
+ case 2:
|
||||
+#line 1 "NONE"
|
||||
+ {te = p+1;}
|
||||
+#line 96 "emoji_presentation_scanner.rl"
|
||||
+ {act = 3;}
|
||||
+ break;
|
||||
+ case 7:
|
||||
+#line 1 "NONE"
|
||||
+ {te = p+1;}
|
||||
+#line 97 "emoji_presentation_scanner.rl"
|
||||
+ {act = 4;}
|
||||
+ break;
|
||||
+#line 188 "emoji_presentation_scanner.c"
|
||||
+ }
|
||||
+
|
||||
+_again:
|
||||
+ switch ( _emoji_presentation_to_state_actions[cs] ) {
|
||||
+ case 5:
|
||||
+#line 1 "NONE"
|
||||
+ {ts = 0;}
|
||||
+ break;
|
||||
+#line 195 "emoji_presentation_scanner.c"
|
||||
+ }
|
||||
+
|
||||
+ if ( ++p != pe )
|
||||
+ goto _resume;
|
||||
+ _test_eof: {}
|
||||
+ if ( p == eof )
|
||||
+ {
|
||||
+ if ( _emoji_presentation_eof_trans[cs] > 0 ) {
|
||||
+ _trans = _emoji_presentation_eof_trans[cs] - 1;
|
||||
+ goto _eof_trans;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+#line 118 "emoji_presentation_scanner.rl"
|
||||
+
|
||||
+
|
||||
+ /* Should not be reached. */
|
||||
+ *is_emoji = false;
|
||||
+ *has_vs = false;
|
||||
+ return p;
|
||||
+}
|
||||
diff --git a/src/3rdparty/emoji-segmenter/patch/0001-Compile-with-warnings-are-errors.patch b/src/3rdparty/emoji-segmenter/patch/0001-Compile-with-warnings-are-errors.patch
|
||||
new file mode 100644
|
||||
index 0000000000..0cc1868ca7
|
||||
--- /dev/null
|
||||
+++ b/src/3rdparty/emoji-segmenter/patch/0001-Compile-with-warnings-are-errors.patch
|
||||
@@ -0,0 +1,26 @@
|
||||
+From 4ced1426e27320e00b0dd28693df5d95c648d230 Mon Sep 17 00:00:00 2001
|
||||
+From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||
+Date: Thu, 14 Nov 2024 09:42:11 +0100
|
||||
+Subject: [PATCH] Compile with warnings-are-errors
|
||||
+
|
||||
+Change-Id: Icea8febefc90f3f047143e5b76ff511145c0dcae
|
||||
+---
|
||||
+ src/3rdparty/emoji-segmenter/emoji_presentation_scanner.c | 2 ++
|
||||
+ 1 file changed, 2 insertions(+)
|
||||
+
|
||||
+diff --git a/src/3rdparty/emoji-segmenter/emoji_presentation_scanner.c b/src/3rdparty/emoji-segmenter/emoji_presentation_scanner.c
|
||||
+index 56e2e78033..ce7e01846c 100644
|
||||
+--- a/src/3rdparty/emoji-segmenter/emoji_presentation_scanner.c
|
||||
++++ b/src/3rdparty/emoji-segmenter/emoji_presentation_scanner.c
|
||||
+@@ -101,6 +101,8 @@ scan_emoji_presentation (emoji_text_iter_t p,
|
||||
+ emoji_text_iter_t te;
|
||||
+ const emoji_text_iter_t eof = pe;
|
||||
+
|
||||
++ (void)ts;
|
||||
++
|
||||
+ unsigned act;
|
||||
+ int cs;
|
||||
+
|
||||
+--
|
||||
+2.40.0.windows.1
|
||||
+
|
||||
diff --git a/src/3rdparty/emoji-segmenter/qt_attribution.json b/src/3rdparty/emoji-segmenter/qt_attribution.json
|
||||
new file mode 100644
|
||||
index 0000000000..64083381d4
|
||||
--- /dev/null
|
||||
+++ b/src/3rdparty/emoji-segmenter/qt_attribution.json
|
||||
@@ -0,0 +1,16 @@
|
||||
+{
|
||||
+ "Id": "emoji-segmenter",
|
||||
+ "Name": "Emoji Segmenter",
|
||||
+ "QDocModule": "qtgui",
|
||||
+ "QtUsage": "Used in QtGui for parsing complex emoji sequences. Can be configured using the -emojisegmenter option.",
|
||||
+ "SecurityCritical": true,
|
||||
+
|
||||
+ "Description": "A parser for emoji sequences.",
|
||||
+ "Homepage": "https://github.com/google/emoji-segmenter",
|
||||
+ "Version": "0.4.0",
|
||||
+ "DownloadLocation": "https://github.com/google/emoji-segmenter/releases/tag/0.4.0",
|
||||
+
|
||||
+ "License": "Apache License 2.0",
|
||||
+ "LicenseId": "Apache-2.0",
|
||||
+ "Copyright": "Copyright 2019 Google LLC"
|
||||
+}
|
||||
diff --git a/src/gui/configure.cmake b/src/gui/configure.cmake
|
||||
index b7c1e8e00c..7889445976 100644
|
||||
--- a/src/gui/configure.cmake
|
||||
+++ b/src/gui/configure.cmake
|
||||
@@ -699,6 +699,12 @@ qt_feature("direct2d1_1" PRIVATE
|
||||
LABEL "Direct 2D 1.1"
|
||||
CONDITION QT_FEATURE_direct2d AND TEST_d2d1_1
|
||||
)
|
||||
+qt_feature("emojisegmenter" PUBLIC PRIVATE
|
||||
+ SECTION "Fonts"
|
||||
+ LABEL "Emoji Segmenter"
|
||||
+ PURPOSE "Supports parsing complex emoji sequences for better font resolution."
|
||||
+)
|
||||
+qt_feature_definition("emojisegmenter" "QT_NO_EMOJISEGMENTER" NEGATE VALUE "1")
|
||||
qt_feature("evdev" PRIVATE
|
||||
LABEL "evdev"
|
||||
CONDITION QT_FEATURE_thread AND TEST_evdev
|
||||
@@ -1299,6 +1305,7 @@ qt_feature("wayland" PUBLIC
|
||||
|
||||
qt_configure_add_summary_section(NAME "Qt Gui")
|
||||
qt_configure_add_summary_entry(ARGS "accessibility")
|
||||
+qt_configure_add_summary_entry(ARGS "emojisegmenter")
|
||||
qt_configure_add_summary_entry(ARGS "freetype")
|
||||
qt_configure_add_summary_entry(ARGS "system-freetype")
|
||||
qt_configure_add_summary_entry(ARGS "harfbuzz")
|
||||
diff --git a/src/gui/qt_cmdline.cmake b/src/gui/qt_cmdline.cmake
|
||||
index 446618ebc4..5465b2c63e 100644
|
||||
--- a/src/gui/qt_cmdline.cmake
|
||||
+++ b/src/gui/qt_cmdline.cmake
|
||||
@@ -10,6 +10,7 @@ qt_commandline_option(eglfs TYPE boolean)
|
||||
qt_commandline_option(evdev TYPE boolean)
|
||||
qt_commandline_option(fontconfig TYPE boolean)
|
||||
qt_commandline_option(freetype TYPE enum VALUES no qt system)
|
||||
+qt_commandline_option(emojisegmenter TYPE boolean)
|
||||
qt_commandline_option(gbm TYPE boolean)
|
||||
qt_commandline_option(gif TYPE boolean)
|
||||
qt_commandline_option(harfbuzz TYPE enum VALUES no qt system)
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
From a43c7e58046604796aa69974ea1c5d3e2648c755 Mon Sep 17 00:00:00 2001
|
||||
From: Thiago Macieira <thiago.macieira@intel.com>
|
||||
Date: Fri, 24 Jan 2025 11:07:58 -0800
|
||||
Subject: [PATCH] QLibraryInfo: speed up checking if ":/qt/etc/qt.conf"
|
||||
resource exists
|
||||
|
||||
Go straight for QResource, because this is run very early in Qt's
|
||||
initialization, usually as a result of some debug message, via
|
||||
QLoggingRegistry::initializeRules(). This bypasses the need to create
|
||||
QResourceFileEnginePrivate, QResourceFileEngine, QFileInfoPrivate, and
|
||||
QFileInfo, all of which would end up in this .isValid() call.
|
||||
|
||||
Additionally, I'm making it query in the C locale, which will also avoid
|
||||
initializing the system & default QLocales. If a resource exists in any
|
||||
language, the C locale query will find it.
|
||||
|
||||
Task-number: QTBUG-133206
|
||||
Change-Id: I434b498903d793c12d35fffd3e297bfdbdc1b6fe
|
||||
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
|
||||
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
||||
(cherry picked from commit d59e640c868f3db2d661970f3d34a22013d49053)
|
||||
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
|
||||
(cherry picked from commit ae2502b4ad3d1215211bf4ed44037a40f52a313d)
|
||||
---
|
||||
src/corelib/global/qlibraryinfo.cpp | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
|
||||
index 94f3e60deba..5f6042be29d 100644
|
||||
--- a/src/corelib/global/qlibraryinfo.cpp
|
||||
+++ b/src/corelib/global/qlibraryinfo.cpp
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "qstringlist.h"
|
||||
#include "qfile.h"
|
||||
#if QT_CONFIG(settings)
|
||||
+#include "qresource.h"
|
||||
#include "qsettings.h"
|
||||
#endif
|
||||
#include "qlibraryinfo.h"
|
||||
@@ -103,7 +104,7 @@ static std::unique_ptr<QSettings> findConfiguration()
|
||||
return std::make_unique<QSettings>(*qtconfManualPath, QSettings::IniFormat);
|
||||
|
||||
QString qtconfig = QStringLiteral(":/qt/etc/qt.conf");
|
||||
- if (QFile::exists(qtconfig))
|
||||
+ if (QResource(qtconfig, QLocale::c()).isValid())
|
||||
return std::make_unique<QSettings>(qtconfig, QSettings::IniFormat);
|
||||
#ifdef Q_OS_DARWIN
|
||||
CFBundleRef bundleRef = CFBundleGetMainBundle();
|
||||
--
|
||||
GitLab
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
From 2ef615228bba9a8eb282437bfb7472f925610e89 Mon Sep 17 00:00:00 2001
|
||||
From: Thiago Macieira <thiago.macieira@intel.com>
|
||||
Date: Fri, 24 Jan 2025 10:28:30 -0800
|
||||
Subject: [PATCH] QSystemLocale: bail out if accessed post-destruction
|
||||
|
||||
There's little we can do, but a lot of content ends up in QLocale very
|
||||
late in the execution. Let's at least not crash.
|
||||
|
||||
Task-number: QTBUG-133206
|
||||
Change-Id: I77d41141cb115147f9befffdd5e69dac19c96044
|
||||
Reviewed-by: Albert Astals Cid <aacid@kde.org>
|
||||
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
|
||||
(cherry picked from commit e32f28034ad2383393645777bcd96eab3f696076)
|
||||
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
|
||||
(cherry picked from commit d5c5f9f3529b384d0d4bea2d51f0ad6a3d57481d)
|
||||
---
|
||||
src/corelib/text/qlocale_unix.cpp | 2 ++
|
||||
src/corelib/text/qlocale_win.cpp | 2 ++
|
||||
2 files changed, 4 insertions(+)
|
||||
|
||||
diff --git a/src/corelib/text/qlocale_unix.cpp b/src/corelib/text/qlocale_unix.cpp
|
||||
index a934f24c016..91dbb74c207 100644
|
||||
--- a/src/corelib/text/qlocale_unix.cpp
|
||||
+++ b/src/corelib/text/qlocale_unix.cpp
|
||||
@@ -127,6 +127,8 @@ QLocale QSystemLocale::fallbackLocale() const
|
||||
QVariant QSystemLocale::query(QueryType type, QVariant &&in) const
|
||||
{
|
||||
QSystemLocaleData *d = qSystemLocaleData();
|
||||
+ if (!d)
|
||||
+ return QVariant();
|
||||
|
||||
if (type == LocaleChanged) {
|
||||
d->readEnvironment();
|
||||
diff --git a/src/corelib/text/qlocale_win.cpp b/src/corelib/text/qlocale_win.cpp
|
||||
index 9fdb46a4c92..793751daaf0 100644
|
||||
--- a/src/corelib/text/qlocale_win.cpp
|
||||
+++ b/src/corelib/text/qlocale_win.cpp
|
||||
@@ -828,6 +828,8 @@ QLocale QSystemLocale::fallbackLocale() const
|
||||
QVariant QSystemLocale::query(QueryType type, QVariant &&in) const
|
||||
{
|
||||
QSystemLocalePrivate *d = systemLocalePrivate();
|
||||
+ if (!d)
|
||||
+ return QVariant();
|
||||
switch(type) {
|
||||
case DecimalPoint:
|
||||
return d->decimalPoint();
|
||||
--
|
||||
GitLab
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
From 12d4bf1ab52748cb84894f50d437064b439e0b7d Mon Sep 17 00:00:00 2001
|
||||
From: Thiago Macieira <thiago.macieira@intel.com>
|
||||
Date: Fri, 24 Jan 2025 10:43:38 -0800
|
||||
Subject: [PATCH] QLocale: try to survive being created during application shut
|
||||
down
|
||||
|
||||
QLocale is very often accessed during global static destructors, so
|
||||
let's try and survive if the default has already been destroyed. In that
|
||||
case, we shall fall back to the C locale.
|
||||
|
||||
I've placed the call to systemData(), which updates the system locale,
|
||||
before the initialization of defaultLocalePrivate, as the initialization
|
||||
of the latter depends on the former.
|
||||
|
||||
Task-number: QTBUG-133206
|
||||
Change-Id: I48e29b45f9be4514336cfffdf5affa5631a956a3
|
||||
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
|
||||
Reviewed-by: Albert Astals Cid <aacid@kde.org>
|
||||
(cherry picked from commit e0a1f491567f2495443babc5aa36a038260f96c6)
|
||||
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
|
||||
(cherry picked from commit bcc0e6124a2ec80df535178d056324433f9ff984)
|
||||
---
|
||||
src/corelib/text/qlocale.cpp | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp
|
||||
index 4f5b5452648..eff083b3d94 100644
|
||||
--- a/src/corelib/text/qlocale.cpp
|
||||
+++ b/src/corelib/text/qlocale.cpp
|
||||
@@ -1112,10 +1112,13 @@ QLocale::QLocale(QStringView name)
|
||||
*/
|
||||
|
||||
QLocale::QLocale()
|
||||
- : d(*defaultLocalePrivate)
|
||||
+ : d(c_private())
|
||||
{
|
||||
- // Make sure system data is up to date:
|
||||
- systemData();
|
||||
+ if (!defaultLocalePrivate.isDestroyed()) {
|
||||
+ // Make sure system data is up to date:
|
||||
+ systemData();
|
||||
+ d = *defaultLocalePrivate;
|
||||
+ }
|
||||
}
|
||||
|
||||
/*!
|
||||
--
|
||||
GitLab
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
From 0acbd22508cb793461c01979d89c529f86a24bc3 Mon Sep 17 00:00:00 2001
|
||||
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||
Date: Wed, 15 Jan 2025 15:12:41 +0100
|
||||
Subject: [PATCH] Request actual font family request in final color font fail safe
|
||||
|
||||
When we're trying to resolve a font for color emojis, we will
|
||||
prefer any color font over the selected font (since a normal
|
||||
font may have monochrome glyphs for emoji characters and that's
|
||||
not what we are after).
|
||||
|
||||
If there are no color fonts on the system at all, we need to do
|
||||
a final match where we ignore whether the font is in color or
|
||||
not and just return it anyway.
|
||||
|
||||
In this final pass we would find the first best match among the
|
||||
fallbacks (typically the first one), but never actually check
|
||||
the font that was requested in the first place. This was a
|
||||
mistake. Unless it does not exist, we should just return the
|
||||
requested font family.
|
||||
|
||||
Pick-to: 6.9
|
||||
Task-number: QTBUG-132377
|
||||
Change-Id: Ie53a6bd665ebdaaca92bf0c33fabf5195e1aa5fe
|
||||
---
|
||||
|
||||
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
|
||||
index 0c2a4b66..03f29009 100644
|
||||
--- a/src/gui/text/qfontdatabase.cpp
|
||||
+++ b/src/gui/text/qfontdatabase.cpp
|
||||
@@ -2787,8 +2787,14 @@ QFontEngine *QFontDatabasePrivate::findFont(const QFontDef &req,
|
||||
// If we are looking for a color font and there are no color fonts on the system,
|
||||
// we will end up here, for one final pass. This is a rare occurrence so we accept
|
||||
// and extra pass on the fallbacks for this.
|
||||
- if (!engine && script == QFontDatabasePrivate::Script_Emoji)
|
||||
+ if (!engine && script == QFontDatabasePrivate::Script_Emoji) {
|
||||
engine = findMatchingFallback(QChar::Script_Common, script);
|
||||
+
|
||||
+ // Since we no longer require color fonts, we need to retry to check if the
|
||||
+ // actual requested font is available as a non-color font.
|
||||
+ if (!requestFamily.isEmpty())
|
||||
+ fallbacks.prepend(requestFamily);
|
||||
+ }
|
||||
}
|
||||
|
||||
if (!engine)
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
diff --git a/cmake/QtPublicWalkLibsHelpers.cmake b/cmake/QtPublicWalkLibsHelpers.cmake
|
||||
index 959283ac..d2d6d70e 100644
|
||||
--- a/cmake/QtPublicWalkLibsHelpers.cmake
|
||||
+++ b/cmake/QtPublicWalkLibsHelpers.cmake
|
||||
@@ -255,8 +255,8 @@ function(__qt_internal_walk_libs
|
||||
__qt_internal_promote_target_to_global(${lib_target_unaliased})
|
||||
endif()
|
||||
endif()
|
||||
- elseif("${lib_target}" MATCHES "^(Qt|${QT_CMAKE_EXPORT_NAMESPACE})::(.*)")
|
||||
- message(FATAL_ERROR "The ${CMAKE_MATCH_2} target is mentioned as a dependency for \
|
||||
+ elseif("${lib_target}" MATCHES "^Qt::(.*)")
|
||||
+ message(FATAL_ERROR "The ${CMAKE_MATCH_1} target is mentioned as a dependency for \
|
||||
${target}, but not declared.")
|
||||
else()
|
||||
if(NOT operation MATCHES "^(collect|direct)_targets$")
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
From cb2633468413d8c2a9e28d4c4a10b25e90dd3116 Mon Sep 17 00:00:00 2001
|
||||
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||
Date: Mon, 25 Nov 2024 16:05:09 +0100
|
||||
Subject: Skip ad hoc handling of variation selector in font merging
|
||||
|
||||
Since we now support emoji parsing, there is no longer any need
|
||||
for this ad hoc processing of VS-16. The exception is if Qt is
|
||||
built without the emoji segmenter, in which case we should keep
|
||||
it for consistency with previous versions.
|
||||
|
||||
Task-number: QTBUG-111801
|
||||
Change-Id: I3e243b9610fe55dda26eba63ac849e6afa22a185
|
||||
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
|
||||
|
||||
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
|
||||
index 02595b40c5..6be6a5aca2 100644
|
||||
--- a/src/gui/text/qfontengine.cpp
|
||||
+++ b/src/gui/text/qfontengine.cpp
|
||||
@@ -1997,8 +1997,11 @@ int QFontEngineMulti::stringToCMap(const QChar *str, int len,
|
||||
int glyph_pos = 0;
|
||||
QStringIterator it(str, str + len);
|
||||
|
||||
- int lastFallback = -1;
|
||||
+#if defined(QT_NO_EMOJISEGMENTER)
|
||||
char32_t previousUcs4 = 0;
|
||||
+#endif
|
||||
+
|
||||
+ int lastFallback = -1;
|
||||
while (it.hasNext()) {
|
||||
const char32_t ucs4 = it.peekNext();
|
||||
|
||||
@@ -2057,6 +2060,7 @@ int QFontEngineMulti::stringToCMap(const QChar *str, int len,
|
||||
}
|
||||
}
|
||||
|
||||
+#if defined(QT_NO_EMOJISEGMENTER)
|
||||
// For variant-selectors, they are modifiers to the previous character. If we
|
||||
// end up with different font selections for the selector and the character it
|
||||
// modifies, we try applying the selector font to the preceding character as well
|
||||
@@ -2095,11 +2099,15 @@ int QFontEngineMulti::stringToCMap(const QChar *str, int len,
|
||||
}
|
||||
}
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
|
||||
it.advance();
|
||||
++glyph_pos;
|
||||
+
|
||||
+#if defined(QT_NO_EMOJISEGMENTER)
|
||||
previousUcs4 = ucs4;
|
||||
+#endif
|
||||
}
|
||||
|
||||
*nglyphs = glyph_pos;
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
From aaf7437db3a520ab14220a46cf9427cb9a8d915c Mon Sep 17 00:00:00 2001
|
||||
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||
Date: Fri, 29 Nov 2024 15:27:10 +0100
|
||||
Subject: [PATCH] Support variation selector when emoji segmenter is disabled
|
||||
|
||||
This amends cb2633468413d8c2a9e28d4c4a10b25e90dd3116.
|
||||
|
||||
The patch excluded the ad hoc parsing of variation selector
|
||||
except when Qt was built without the emoji segmenter. The
|
||||
reasoning being that the emoji parsing handles this correctly
|
||||
now.
|
||||
|
||||
However, when setting the QT_DISABLE_EMOJI_SEGMENTER variable
|
||||
in the environment, this is supposed to work as a fail safe
|
||||
which gives you the original behavior, in case there are
|
||||
regressions. Therefore, the variation selector handling needs
|
||||
to be run also when this environment variable is set.
|
||||
|
||||
Pick-to: 6.9
|
||||
Change-Id: I2669d29016a552775461aad13e50459baecdc26f
|
||||
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
|
||||
---
|
||||
src/gui/text/qfontengine.cpp | 19 ++++++++++++-------
|
||||
src/gui/text/qfontengine_p.h | 2 ++
|
||||
src/gui/text/qtextengine.cpp | 3 +--
|
||||
3 files changed, 15 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
|
||||
index b5183dfd..60d46c5b 100644
|
||||
--- a/src/gui/text/qfontengine.cpp
|
||||
+++ b/src/gui/text/qfontengine.cpp
|
||||
@@ -1526,6 +1526,16 @@ QFontEngine::GlyphCacheEntry &QFontEngine::GlyphCacheEntry::operator=(const Glyp
|
||||
return *this;
|
||||
}
|
||||
|
||||
+bool QFontEngine::disableEmojiSegmenter()
|
||||
+{
|
||||
+#if defined(QT_NO_EMOJISEGMENTER)
|
||||
+ return true;
|
||||
+#else
|
||||
+ static const bool sDisableEmojiSegmenter = qEnvironmentVariableIntValue("QT_DISABLE_EMOJI_SEGMENTER") > 0;
|
||||
+ return sDisableEmojiSegmenter;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
// ------------------------------------------------------------------
|
||||
// The box font engine
|
||||
// ------------------------------------------------------------------
|
||||
@@ -1884,9 +1894,8 @@ int QFontEngineMulti::stringToCMap(const QChar *str, int len,
|
||||
int glyph_pos = 0;
|
||||
QStringIterator it(str, str + len);
|
||||
|
||||
-#if defined(QT_NO_EMOJISEGMENTER)
|
||||
+ const bool enableVariationSelectorHack = disableEmojiSegmenter();
|
||||
char32_t previousUcs4 = 0;
|
||||
-#endif
|
||||
|
||||
int lastFallback = -1;
|
||||
while (it.hasNext()) {
|
||||
@@ -1947,12 +1956,11 @@ int QFontEngineMulti::stringToCMap(const QChar *str, int len,
|
||||
}
|
||||
}
|
||||
|
||||
-#if defined(QT_NO_EMOJISEGMENTER)
|
||||
// For variant-selectors, they are modifiers to the previous character. If we
|
||||
// end up with different font selections for the selector and the character it
|
||||
// modifies, we try applying the selector font to the preceding character as well
|
||||
const int variantSelectorBlock = 0xFE00;
|
||||
- if ((ucs4 & 0xFFF0) == variantSelectorBlock && glyph_pos > 0) {
|
||||
+ if (enableVariationSelectorHack && (ucs4 & 0xFFF0) == variantSelectorBlock && glyph_pos > 0) {
|
||||
int selectorFontEngine = glyphs->glyphs[glyph_pos] >> 24;
|
||||
int precedingCharacterFontEngine = glyphs->glyphs[glyph_pos - 1] >> 24;
|
||||
|
||||
@@ -1986,15 +1994,12 @@ int QFontEngineMulti::stringToCMap(const QChar *str, int len,
|
||||
}
|
||||
}
|
||||
}
|
||||
-#endif
|
||||
}
|
||||
|
||||
it.advance();
|
||||
++glyph_pos;
|
||||
|
||||
-#if defined(QT_NO_EMOJISEGMENTER)
|
||||
previousUcs4 = ucs4;
|
||||
-#endif
|
||||
}
|
||||
|
||||
*nglyphs = glyph_pos;
|
||||
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
|
||||
index b56c3792..9ef4b29d 100644
|
||||
--- a/src/gui/text/qfontengine_p.h
|
||||
+++ b/src/gui/text/qfontengine_p.h
|
||||
@@ -255,6 +255,8 @@ public:
|
||||
virtual bool hasUnreliableGlyphOutline() const;
|
||||
virtual bool expectsGammaCorrectedBlending() const;
|
||||
|
||||
+ static bool disableEmojiSegmenter();
|
||||
+
|
||||
enum HintStyle {
|
||||
HintNone,
|
||||
HintLight,
|
||||
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
|
||||
index a04cd9a7..8d13517f 100644
|
||||
--- a/src/gui/text/qtextengine.cpp
|
||||
+++ b/src/gui/text/qtextengine.cpp
|
||||
@@ -1953,7 +1953,7 @@ namespace {
|
||||
|
||||
void QTextEngine::itemize() const
|
||||
{
|
||||
- static bool disableEmojiSegmenter = qEnvironmentVariableIntValue("QT_DISABLE_EMOJI_SEGMENTER") > 0;
|
||||
+ const bool disableEmojiSegmenter = QFontEngine::disableEmojiSegmenter();
|
||||
validate();
|
||||
if (layoutData->items.size())
|
||||
return;
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
From dc87345703228bd3e86da74d7fd22e77c81f6056 Mon Sep 17 00:00:00 2001
|
||||
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||
Date: Wed, 12 Feb 2025 13:58:36 +0100
|
||||
Subject: [PATCH] Treat variation selectors as ignorable chars
|
||||
|
||||
The variation selectors only make sense in the context of the
|
||||
previous glyph and should never be shaped by themselves, therefore
|
||||
we should not pick a different font engine for these even if
|
||||
the cmap does not support it. They are sometimes needed to
|
||||
properly resolve the emojis, but the OpenType rules in the font
|
||||
may not be written with them in mind.
|
||||
|
||||
If the cmap lookup fails for these, then Harfbuzz will map them
|
||||
to a zero-width space, thus ignoring them when resolving the
|
||||
OpenType rules.
|
||||
|
||||
We treat these the same as other control characters and just
|
||||
ignore them when doing font merging.
|
||||
|
||||
Note: This was handled through an ad hoc mechanism prior to
|
||||
the introduction of the emoji segmenter in 6.9.When the emoji
|
||||
segmenter is disabled, we still use this mechanism, which
|
||||
depends on us not ignoring the character in that case.
|
||||
|
||||
Pick-to: 6.9
|
||||
Fixes: QTBUG-133480
|
||||
Change-Id: I8fa4e8d5e1aabad0946b8fd3fff044e2b2af5d0e
|
||||
---
|
||||
|
||||
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
|
||||
index 032a8b7..4d1243c 100644
|
||||
--- a/src/gui/text/qfontengine_p.h
|
||||
+++ b/src/gui/text/qfontengine_p.h
|
||||
@@ -159,6 +159,7 @@
|
||||
|| ucs4 == QChar::LineFeed
|
||||
|| ucs4 == QChar::CarriageReturn
|
||||
|| ucs4 == QChar::ParagraphSeparator
|
||||
+ || (!disableEmojiSegmenter() && (ucs4 & 0xFFF0) == 0xFE00)
|
||||
|| QChar::category(ucs4) == QChar::Other_Control;
|
||||
}
|
||||
|
||||
diff --git a/tests/baseline/painting/scripts/glyphruns.qps b/tests/baseline/painting/scripts/glyphruns.qps
|
||||
index 2b70c72..0683ef5 100644
|
||||
--- a/tests/baseline/painting/scripts/glyphruns.qps
|
||||
+++ b/tests/baseline/painting/scripts/glyphruns.qps
|
||||
@@ -143,7 +143,7 @@
|
||||
save
|
||||
setPen black
|
||||
setFont "sansserif" 16 normal
|
||||
- drawGlyphRun 0 40 "e😃m😇o😍j😜i😸!"
|
||||
+ drawGlyphRun 0 40 "e😃m👩️⚕️o😍j😜i😸!"
|
||||
restore
|
||||
|
||||
translate 0 55
|
||||
File diff suppressed because it is too large
Load diff
174
qtbase-wayland-compress-high-frequency-mouse-events.patch
Normal file
174
qtbase-wayland-compress-high-frequency-mouse-events.patch
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
From 095759818854e5a011aa8f859e566bbc6368ab76 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= <mumei6102@gmail.com>
|
||||
Date: Sun, 27 Jul 2025 00:50:00 +0200
|
||||
Subject: [PATCH] wayland: Compress high frequency mouse events
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Add support for Qt::AA_CompressHighFrequencyEvents on Wayland.
|
||||
|
||||
The highest USB HID polling rate is 8 kHz (125 μs). Most mice use lower
|
||||
polling rate [125 Hz - 1000 Hz]. Reject all events faster than 100 μs,
|
||||
because it definitely means the application main thread is freezed by
|
||||
the long operation and events are delivered one after another from the
|
||||
queue. Since now we rely on the 0 ms timer to deliver the last pending
|
||||
event when application main thread is no longer freezed.
|
||||
|
||||
Pick-to: 6.10
|
||||
Task-number: QTBUG-138706
|
||||
Change-Id: Ie9d539e233c5551b1756d599b65495571e195f9d
|
||||
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||
---
|
||||
src/corelib/global/qnamespace.qdoc | 1 +
|
||||
.../platforms/wayland/qwaylandinputdevice.cpp | 38 +++++++++++++++++++
|
||||
.../platforms/wayland/qwaylandinputdevice_p.h | 12 ++++++
|
||||
.../platforms/wayland/qwaylandintegration.cpp | 2 +
|
||||
tests/auto/wayland/client/tst_client.cpp | 2 +
|
||||
5 files changed, 55 insertions(+)
|
||||
|
||||
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
|
||||
index c845cfa7..f463d736 100644
|
||||
--- a/src/corelib/global/qnamespace.qdoc
|
||||
+++ b/src/corelib/global/qnamespace.qdoc
|
||||
@@ -227,6 +227,7 @@
|
||||
application later.
|
||||
On Windows 8 and above the default value is also true, but it only applies
|
||||
to touch events. Mouse and window events remain unaffected by this flag.
|
||||
+ On Wayland the default value is also true, but it only applies to mouse events.
|
||||
On other platforms, the default is false.
|
||||
(In the future, the compression feature may be implemented across platforms.)
|
||||
You can test the attribute to see whether compression is enabled.
|
||||
diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
|
||||
index 170e80f8..45c78765 100644
|
||||
--- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
|
||||
+++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
|
||||
@@ -63,6 +63,34 @@ Q_LOGGING_CATEGORY(lcQpaWaylandInput, "qt.qpa.wayland.input");
|
||||
// reasonable number of them. As of 2021 most touchscreen panels support 10 concurrent touchpoints.
|
||||
static const int MaxTouchPoints = 10;
|
||||
|
||||
+QWaylandEventCompressionPrivate::QWaylandEventCompressionPrivate()
|
||||
+{
|
||||
+ timeElapsed.start();
|
||||
+ delayTimer.setSingleShot(true);
|
||||
+}
|
||||
+
|
||||
+bool QWaylandEventCompressionPrivate::compressEvent()
|
||||
+{
|
||||
+ using namespace std::chrono_literals;
|
||||
+
|
||||
+ if (!QCoreApplication::testAttribute(Qt::AA_CompressHighFrequencyEvents))
|
||||
+ return false;
|
||||
+
|
||||
+ const auto elapsed = timeElapsed.durationElapsed();
|
||||
+ timeElapsed.start();
|
||||
+ if (elapsed < 100us || delayTimer.isActive())
|
||||
+ {
|
||||
+ // The highest USB HID polling rate is 8 kHz (125 μs). Most mice use lowe polling rate [125 Hz - 1000 Hz].
|
||||
+ // Reject all events faster than 100 μs, because it definitely means the application main thread is
|
||||
+ // freezed by long operation and events are delivered one after another from the queue. Since now we rely
|
||||
+ // on the 0 ms timer to deliver the last pending event when application main thread is no longer freezed.
|
||||
+ delayTimer.start(0);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
QWaylandInputDevice::Keyboard::Keyboard(QWaylandInputDevice *p)
|
||||
: mParent(p)
|
||||
{
|
||||
@@ -140,6 +168,8 @@ QWaylandInputDevice::Pointer::Pointer(QWaylandInputDevice *seat)
|
||||
cursorTimerCallback();
|
||||
});
|
||||
#endif
|
||||
+
|
||||
+ mEventCompression.delayTimer.callOnTimeout(this, &QWaylandInputDevice::Pointer::flushFrameEvent);
|
||||
}
|
||||
|
||||
QWaylandInputDevice::Pointer::~Pointer()
|
||||
@@ -922,6 +952,11 @@ void QWaylandInputDevice::Pointer::pointer_axis(uint32_t time, uint32_t axis, in
|
||||
|
||||
void QWaylandInputDevice::Pointer::pointer_frame()
|
||||
{
|
||||
+ if (mEventCompression.compressEvent()) {
|
||||
+ qCDebug(lcQpaWaylandInput) << "compressed pointer_frame event";
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
flushFrameEvent();
|
||||
}
|
||||
|
||||
@@ -1051,6 +1086,7 @@ void QWaylandInputDevice::Pointer::setFrameEvent(QWaylandPointerEvent *event)
|
||||
flushFrameEvent();
|
||||
}
|
||||
|
||||
+ delete mFrameData.event;
|
||||
mFrameData.event = event;
|
||||
|
||||
if (version() < WL_POINTER_FRAME_SINCE_VERSION) {
|
||||
@@ -1170,6 +1206,8 @@ void QWaylandInputDevice::Pointer::flushScrollEvent()
|
||||
|
||||
void QWaylandInputDevice::Pointer::flushFrameEvent()
|
||||
{
|
||||
+ mEventCompression.delayTimer.stop();
|
||||
+
|
||||
if (auto *event = mFrameData.event) {
|
||||
if (auto window = event->surface) {
|
||||
window->handleMouse(mParent, *event);
|
||||
diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice_p.h b/src/plugins/platforms/wayland/qwaylandinputdevice_p.h
|
||||
index bcaf0258..0b24999e 100644
|
||||
--- a/src/plugins/platforms/wayland/qwaylandinputdevice_p.h
|
||||
+++ b/src/plugins/platforms/wayland/qwaylandinputdevice_p.h
|
||||
@@ -75,6 +75,16 @@ class CursorSurface;
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(lcQpaWaylandInput);
|
||||
|
||||
+struct QWaylandEventCompressionPrivate
|
||||
+{
|
||||
+ QWaylandEventCompressionPrivate();
|
||||
+
|
||||
+ bool compressEvent();
|
||||
+
|
||||
+ QElapsedTimer timeElapsed;
|
||||
+ QTimer delayTimer;
|
||||
+};
|
||||
+
|
||||
class Q_WAYLANDCLIENT_EXPORT QWaylandInputDevice
|
||||
: public QObject
|
||||
, public QtWayland::wl_seat
|
||||
@@ -381,6 +391,8 @@ public:
|
||||
bool mScrollBeginSent = false;
|
||||
QPointF mScrollDeltaRemainder;
|
||||
|
||||
+ QWaylandEventCompressionPrivate mEventCompression;
|
||||
+
|
||||
void setFrameEvent(QWaylandPointerEvent *event);
|
||||
void flushScrollEvent();
|
||||
void flushFrameEvent();
|
||||
diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp
|
||||
index 669d47ee..fc869de6 100644
|
||||
--- a/src/plugins/platforms/wayland/qwaylandintegration.cpp
|
||||
+++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp
|
||||
@@ -87,6 +87,8 @@ QWaylandIntegration::QWaylandIntegration(const QString &platformName)
|
||||
: mPlatformName(platformName), mFontDb(new QGenericUnixFontDatabase())
|
||||
#endif
|
||||
{
|
||||
+ QCoreApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents);
|
||||
+
|
||||
mDisplay.reset(new QWaylandDisplay(this));
|
||||
mPlatformServices.reset(new QWaylandPlatformServices(mDisplay.data()));
|
||||
|
||||
diff --git a/tests/auto/wayland/client/tst_client.cpp b/tests/auto/wayland/client/tst_client.cpp
|
||||
index 04400e3f..09ac4f7f 100644
|
||||
--- a/tests/auto/wayland/client/tst_client.cpp
|
||||
+++ b/tests/auto/wayland/client/tst_client.cpp
|
||||
@@ -276,6 +276,8 @@ void tst_WaylandClient::events()
|
||||
exec([&] {
|
||||
pointer()->sendEnter(s, window.frameOffset() + mousePressPos);
|
||||
pointer()->sendFrame(client());
|
||||
+ pointer()->sendMotion(client(), window.frameOffset() + mousePressPos / 2);
|
||||
+ pointer()->sendFrame(client());
|
||||
pointer()->sendMotion(client(), window.frameOffset() + mousePressPos);
|
||||
pointer()->sendFrame(client());
|
||||
pointer()->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
From 18550cd9ad04913d50abfc88a6048b7cfaf80687 Mon Sep 17 00:00:00 2001
|
||||
From: Igor Khanin <igor@khanin.biz>
|
||||
Date: Mon, 13 Oct 2025 14:26:39 +0300
|
||||
Subject: [PATCH] wayland: Convey preference for server side decorations
|
||||
|
||||
As discussed in the mailing list, Qt applications generally expect top
|
||||
level windows to be decorated by the windowing system - unless
|
||||
explicitly requested by the developer by marking a window as frameless.
|
||||
Furthermore, Qt's client side decorations for Wayland were only really
|
||||
intended as a fallback.
|
||||
|
||||
However until now the Wayland xdg-shell integration conveyed to the
|
||||
compositor (if it supports decorations negotiations) that it didn't
|
||||
care whose responsibility it was to draw window decorations. This did
|
||||
not matter under KWin, which resolves such cases in favor of SSDs - but
|
||||
does matter under other SSD-capable compositors like cosmic-comp (which
|
||||
considers SSDs to be the fallback option).
|
||||
|
||||
This changes the xdg-shell integration code to be explicit about
|
||||
requesting SSDs.
|
||||
|
||||
[ChangeLog][QtWaylandClient][Important Behavior Changes] The Wayland
|
||||
XDG shell integration now requests server side decorations with
|
||||
compositors supporting the zxdg_decoration_manager_v1 protocol.
|
||||
|
||||
Change-Id: Ia025b1f6ff17248a5710f981a0cecd90c47b6cd8
|
||||
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||
---
|
||||
|
||||
diff --git a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
|
||||
index a1a173f..8386b65 100644
|
||||
--- a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
|
||||
+++ b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
|
||||
@@ -201,7 +201,7 @@
|
||||
delete m_decoration;
|
||||
m_decoration = nullptr;
|
||||
} else {
|
||||
- m_decoration->unsetMode();
|
||||
+ m_decoration->requestMode(QWaylandXdgToplevelDecorationV1::mode_server_side);
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/tests/auto/wayland/xdgdecorationv1/tst_xdgdecorationv1.cpp b/tests/auto/wayland/xdgdecorationv1/tst_xdgdecorationv1.cpp
|
||||
index 5ee8569..65ac08f 100644
|
||||
--- a/tests/auto/wayland/xdgdecorationv1/tst_xdgdecorationv1.cpp
|
||||
+++ b/tests/auto/wayland/xdgdecorationv1/tst_xdgdecorationv1.cpp
|
||||
@@ -149,7 +149,7 @@
|
||||
QVERIFY(window.frameMargins().isNull());
|
||||
|
||||
QCOMPOSITOR_TRY_VERIFY(xdgToplevel());
|
||||
- QCOMPOSITOR_TRY_VERIFY(toplevelDecoration()->m_unsetModeRequested);
|
||||
+ QCOMPOSITOR_TRY_VERIFY(toplevelDecoration()->m_requestedMode == XdgToplevelDecorationV1::mode_server_side);
|
||||
QVERIFY(window.frameMargins().isNull()); // We're still waiting for a configure
|
||||
exec([&] {
|
||||
toplevelDecoration()->sendConfigure(XdgToplevelDecorationV1::mode_client_side);
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
From 9dd0d936d6691904a4bb212dcf48999a5228b84f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= <mumei6102@gmail.com>
|
||||
Date: Thu, 7 Aug 2025 15:42:55 +0200
|
||||
Subject: [PATCH] wayland: Enable event compression and fix scroll end event
|
||||
|
||||
We have to deliver the scroll end event in order with other scroll
|
||||
events, so move scroll end event logic into flushScrollEvent().
|
||||
|
||||
Track the target scroll window on scroll begin and check whether we
|
||||
have a target window to prevent a crash.
|
||||
|
||||
Also we can't clear the scroll delta when scroll end event arrives,
|
||||
because the event compression relies on this value.
|
||||
|
||||
Use scoped pointer for frame event to simplify code and make sure it's
|
||||
deleted in destructor.
|
||||
|
||||
Amends 095759818854e5a011aa8f859e566bbc6368ab76
|
||||
Updates 789681872fb62450fc78d1a06472a40d970a8d57
|
||||
|
||||
Change-Id: Ifb149c8fde1286b60439be0dab16b1df65279ea8
|
||||
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||
---
|
||||
.../platforms/wayland/qwaylandinputdevice.cpp | 98 ++++++++++---------
|
||||
.../platforms/wayland/qwaylandinputdevice_p.h | 6 +-
|
||||
.../platforms/wayland/qwaylandintegration.cpp | 2 +
|
||||
3 files changed, 61 insertions(+), 45 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
|
||||
index 7fcda34c57ca..6ce43714a35f 100644
|
||||
--- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
|
||||
+++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
|
||||
@@ -935,10 +935,7 @@ void QWaylandInputDevice::Pointer::pointer_axis(uint32_t time, uint32_t axis, in
|
||||
|
||||
mParent->mTime = time;
|
||||
|
||||
- if (version() < WL_POINTER_FRAME_SINCE_VERSION) {
|
||||
- qCDebug(lcQpaWaylandInput) << "Flushing new event; no frame event in this version";
|
||||
- flushFrameEvent();
|
||||
- }
|
||||
+ maybePointerFrame();
|
||||
}
|
||||
|
||||
void QWaylandInputDevice::Pointer::pointer_frame()
|
||||
@@ -978,11 +975,9 @@ void QWaylandInputDevice::Pointer::pointer_axis_stop(uint32_t time, uint32_t axi
|
||||
switch (axis) {
|
||||
case axis_vertical_scroll:
|
||||
qCDebug(lcQpaWaylandInput) << "Received vertical wl_pointer.axis_stop";
|
||||
- mFrameData.delta.setY(0); //TODO: what's the point of doing this?
|
||||
break;
|
||||
case axis_horizontal_scroll:
|
||||
qCDebug(lcQpaWaylandInput) << "Received horizontal wl_pointer.axis_stop";
|
||||
- mFrameData.delta.setX(0);
|
||||
break;
|
||||
default:
|
||||
qCWarning(lcQpaWaylandInput) << "wl_pointer.axis_stop: Unknown axis: " << axis
|
||||
@@ -990,25 +985,7 @@ void QWaylandInputDevice::Pointer::pointer_axis_stop(uint32_t time, uint32_t axi
|
||||
return;
|
||||
}
|
||||
|
||||
- // May receive axis_stop for events we haven't sent a ScrollBegin for because
|
||||
- // most axis_sources do not mandate an axis_stop event to be sent.
|
||||
- if (!mScrollBeginSent) {
|
||||
- // TODO: For now, we just ignore these events, but we could perhaps take this as an
|
||||
- // indication that this compositor will in fact send axis_stop events for these sources
|
||||
- // and send a ScrollBegin the next time an axis_source event with this type is encountered.
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- QWaylandWindow *target = QWaylandWindow::mouseGrab();
|
||||
- if (!target)
|
||||
- target = focusWindow();
|
||||
- Qt::KeyboardModifiers mods = mParent->modifiers();
|
||||
- const bool inverted = mFrameData.verticalAxisInverted || mFrameData.horizontalAxisInverted;
|
||||
- WheelEvent wheelEvent(focusWindow(), Qt::ScrollEnd, mParent->mTime, mSurfacePos, mGlobalPos,
|
||||
- QPoint(), QPoint(), Qt::MouseEventNotSynthesized, mods, inverted);
|
||||
- target->handleMouse(mParent, wheelEvent);
|
||||
- mScrollBeginSent = false;
|
||||
- mScrollDeltaRemainder = QPointF();
|
||||
+ mScrollEnd = true;
|
||||
}
|
||||
|
||||
void QWaylandInputDevice::Pointer::pointer_axis_discrete(uint32_t axis, int32_t value)
|
||||
@@ -1069,6 +1046,14 @@ void QWaylandInputDevice::Pointer::pointer_axis_relative_direction(uint32_t axis
|
||||
}
|
||||
}
|
||||
|
||||
+inline void QWaylandInputDevice::Pointer::maybePointerFrame()
|
||||
+{
|
||||
+ if (version() < WL_POINTER_FRAME_SINCE_VERSION) {
|
||||
+ qCDebug(lcQpaWaylandInput) << "Flushing new event; no frame event in this version";
|
||||
+ pointer_frame();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void QWaylandInputDevice::Pointer::setFrameEvent(QWaylandPointerEvent *event)
|
||||
{
|
||||
qCDebug(lcQpaWaylandInput) << "Setting frame event " << event->type;
|
||||
@@ -1077,13 +1062,9 @@ void QWaylandInputDevice::Pointer::setFrameEvent(QWaylandPointerEvent *event)
|
||||
flushFrameEvent();
|
||||
}
|
||||
|
||||
- delete mFrameData.event;
|
||||
- mFrameData.event = event;
|
||||
+ mFrameData.event.reset(event);
|
||||
|
||||
- if (version() < WL_POINTER_FRAME_SINCE_VERSION) {
|
||||
- qCDebug(lcQpaWaylandInput) << "Flushing new event; no frame event in this version";
|
||||
- flushFrameEvent();
|
||||
- }
|
||||
+ maybePointerFrame();
|
||||
}
|
||||
|
||||
void QWaylandInputDevice::Pointer::FrameData::resetScrollData()
|
||||
@@ -1163,11 +1144,24 @@ void QWaylandInputDevice::Pointer::flushScrollEvent()
|
||||
{
|
||||
QPoint angleDelta = mFrameData.angleDelta();
|
||||
|
||||
+ // The wayland protocol has separate horizontal and vertical axes, Qt has just the one inverted flag
|
||||
+ // Pragmatically it should't come up
|
||||
+ const bool inverted = mFrameData.verticalAxisInverted || mFrameData.horizontalAxisInverted;
|
||||
+
|
||||
// Angle delta is required for Qt wheel events, so don't try to send events if it's zero
|
||||
if (!angleDelta.isNull()) {
|
||||
- QWaylandWindow *target = QWaylandWindow::mouseGrab();
|
||||
- if (!target)
|
||||
- target = focusWindow();
|
||||
+ QWaylandWindow *target = mScrollTarget;
|
||||
+ if (!mScrollBeginSent) {
|
||||
+ if (!target)
|
||||
+ target = QWaylandWindow::mouseGrab();
|
||||
+ if (!target)
|
||||
+ target = focusWindow();
|
||||
+ }
|
||||
+ if (!target) {
|
||||
+ qCDebug(lcQpaWaylandInput) << "Flushing scroll event aborted - no scroll target";
|
||||
+ mFrameData.resetScrollData();
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
if (isDefinitelyTerminated(mFrameData.axisSource) && !mScrollBeginSent) {
|
||||
qCDebug(lcQpaWaylandInput) << "Flushing scroll event sending ScrollBegin";
|
||||
@@ -1177,21 +1171,38 @@ void QWaylandInputDevice::Pointer::flushScrollEvent()
|
||||
mParent->modifiers(), false));
|
||||
mScrollBeginSent = true;
|
||||
mScrollDeltaRemainder = QPointF();
|
||||
+ mScrollTarget = target;
|
||||
}
|
||||
|
||||
Qt::ScrollPhase phase = mScrollBeginSent ? Qt::ScrollUpdate : Qt::NoScrollPhase;
|
||||
QPoint pixelDelta = mFrameData.pixelDeltaAndError(&mScrollDeltaRemainder);
|
||||
- Qt::MouseEventSource source = mFrameData.wheelEventSource();
|
||||
-
|
||||
-
|
||||
- // The wayland protocol has separate horizontal and vertical axes, Qt has just the one inverted flag
|
||||
- // Pragmatically it should't come up
|
||||
- const bool inverted = mFrameData.verticalAxisInverted || mFrameData.horizontalAxisInverted;
|
||||
|
||||
qCDebug(lcQpaWaylandInput) << "Flushing scroll event" << phase << pixelDelta << angleDelta;
|
||||
target->handleMouse(mParent, WheelEvent(focusWindow(), phase, mParent->mTime, mSurfacePos, mGlobalPos,
|
||||
- pixelDelta, angleDelta, source, mParent->modifiers(), inverted));
|
||||
+ pixelDelta, angleDelta, mFrameData.wheelEventSource(), mParent->modifiers(), inverted));
|
||||
+ }
|
||||
+
|
||||
+ if (mScrollEnd) {
|
||||
+ if (mScrollBeginSent) {
|
||||
+ if (auto target = mScrollTarget.get()) {
|
||||
+ qCDebug(lcQpaWaylandInput) << "Flushing scroll end event";
|
||||
+ target->handleMouse(mParent, WheelEvent(focusWindow(), Qt::ScrollEnd, mParent->mTime, mSurfacePos, mGlobalPos,
|
||||
+ QPoint(), QPoint(), mFrameData.wheelEventSource(), mParent->modifiers(), inverted));
|
||||
+ }
|
||||
+ mScrollBeginSent = false;
|
||||
+ mScrollDeltaRemainder = QPointF();
|
||||
+ } else {
|
||||
+ // May receive axis_stop for events we haven't sent a ScrollBegin for because
|
||||
+ // most axis_sources do not mandate an axis_stop event to be sent.
|
||||
+
|
||||
+ // TODO: For now, we just ignore these events, but we could perhaps take this as an
|
||||
+ // indication that this compositor will in fact send axis_stop events for these sources
|
||||
+ // and send a ScrollBegin the next time an axis_source event with this type is encountered.
|
||||
+ }
|
||||
+ mScrollEnd = false;
|
||||
+ mScrollTarget.clear();
|
||||
}
|
||||
+
|
||||
mFrameData.resetScrollData();
|
||||
}
|
||||
|
||||
@@ -1199,7 +1210,7 @@ void QWaylandInputDevice::Pointer::flushFrameEvent()
|
||||
{
|
||||
mEventCompression.delayTimer.stop();
|
||||
|
||||
- if (auto *event = mFrameData.event) {
|
||||
+ if (auto *event = mFrameData.event.get()) {
|
||||
if (auto window = event->surface) {
|
||||
window->handleMouse(mParent, *event);
|
||||
} else if (mFrameData.event->type == QEvent::MouseButtonRelease) {
|
||||
@@ -1212,8 +1223,7 @@ void QWaylandInputDevice::Pointer::flushFrameEvent()
|
||||
event->modifiers); // , Qt::MouseEventSource source =
|
||||
// Qt::MouseEventNotSynthesized);
|
||||
}
|
||||
- delete mFrameData.event;
|
||||
- mFrameData.event = nullptr;
|
||||
+ mFrameData.event.reset();
|
||||
}
|
||||
|
||||
//TODO: do modifiers get passed correctly here?
|
||||
diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice_p.h b/src/plugins/platforms/wayland/qwaylandinputdevice_p.h
|
||||
index 533a10991e5e..aa2ccddbcdb8 100644
|
||||
--- a/src/plugins/platforms/wayland/qwaylandinputdevice_p.h
|
||||
+++ b/src/plugins/platforms/wayland/qwaylandinputdevice_p.h
|
||||
@@ -370,7 +370,7 @@ private Q_SLOTS:
|
||||
Qt::MouseButton mLastButton = Qt::NoButton;
|
||||
|
||||
struct FrameData {
|
||||
- QWaylandPointerEvent *event = nullptr;
|
||||
+ QScopedPointer<QWaylandPointerEvent> event;
|
||||
|
||||
QPointF delta;
|
||||
QPoint delta120;
|
||||
@@ -387,10 +387,14 @@ private Q_SLOTS:
|
||||
} mFrameData;
|
||||
|
||||
bool mScrollBeginSent = false;
|
||||
+ bool mScrollEnd = false;
|
||||
QPointF mScrollDeltaRemainder;
|
||||
+ QPointer<QWaylandWindow> mScrollTarget;
|
||||
|
||||
QWaylandEventCompressionPrivate mEventCompression;
|
||||
|
||||
+ void maybePointerFrame();
|
||||
+
|
||||
void setFrameEvent(QWaylandPointerEvent *event);
|
||||
void flushScrollEvent();
|
||||
void flushFrameEvent();
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
From c93008e4d06abb0072e0e5e57d84a4ae182ecfc0 Mon Sep 17 00:00:00 2001
|
||||
From: Błażej Szczygieł <mumei6102@gmail.com>
|
||||
Date: Tue, 21 Oct 2025 19:49:17 +0200
|
||||
Subject: [PATCH] wayland: Fix crash in QWaylandShmBackingStore::scroll()
|
||||
|
||||
Fixes a crash when monitor is unplugged while scrolling.
|
||||
|
||||
recreateBackBufferIfNeeded() calls getBuffer() which may set
|
||||
mFrontBuffer to nullptr.
|
||||
|
||||
Amends: 6f25f703fd37a900c139e14a33a4639502bfeae7
|
||||
|
||||
Task-number: QTBUG-139231
|
||||
Change-Id: Ia5bedce2a3f6580c722f73446de81a26d40ea2f4
|
||||
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||
---
|
||||
|
||||
diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp
|
||||
index b853db2..fa70b53 100644
|
||||
--- a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp
|
||||
+++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp
|
||||
@@ -229,7 +229,7 @@
|
||||
// Inspired by QCALayerBackingStore.
|
||||
bool QWaylandShmBackingStore::scroll(const QRegion ®ion, int dx, int dy)
|
||||
{
|
||||
- if (Q_UNLIKELY(!mBackBuffer || !mFrontBuffer))
|
||||
+ if (Q_UNLIKELY(!mBackBuffer))
|
||||
return false;
|
||||
|
||||
const qreal devicePixelRatio = waylandWindow()->scale();
|
||||
@@ -241,6 +241,8 @@
|
||||
return false;
|
||||
|
||||
recreateBackBufferIfNeeded();
|
||||
+ if (!mFrontBuffer)
|
||||
+ return false;
|
||||
|
||||
const QPoint scrollDelta(dx, dy);
|
||||
const QMargins margins = windowDecorationMargins();
|
||||
242
qtbase-wayland-optimize-scroll-operations.patch
Normal file
242
qtbase-wayland-optimize-scroll-operations.patch
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
From 6f25f703fd37a900c139e14a33a4639502bfeae7 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= <mumei6102@gmail.com>
|
||||
Date: Wed, 13 Aug 2025 00:48:08 +0200
|
||||
Subject: [PATCH] wayland: Optimize scroll operation
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Don't copy the dirty region in "recreateBackBufferIfNeeded()" in
|
||||
"beginPaint()". Mark this region as non-dirty in the back buffer
|
||||
and paint. Finalize the back buffer (copy remaining dirty region)
|
||||
before flushing. This allows to optimize scrolling, we no longer
|
||||
have to do a redundant dirty area copy.
|
||||
|
||||
This matches the "QCALayerBackingStore" logic.
|
||||
|
||||
Task-number: QTBUG-139231
|
||||
Change-Id: I6c19491fa8f093de9c9ce7624d8f9b65b0b722c5
|
||||
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
|
||||
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||
---
|
||||
.../wayland/qwaylandshmbackingstore.cpp | 111 ++++++++++++------
|
||||
.../wayland/qwaylandshmbackingstore_p.h | 3 +-
|
||||
2 files changed, 74 insertions(+), 40 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp
|
||||
index d8fc7b18ca34..591e5064ebd6 100644
|
||||
--- a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp
|
||||
+++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp
|
||||
@@ -159,6 +159,8 @@ QWaylandShmBackingStore::QWaylandShmBackingStore(QWindow *window, QWaylandDispla
|
||||
// recreateBackBufferIfNeeded always resets mBackBuffer
|
||||
if (mRequestedSize.isValid() && waylandWindow())
|
||||
recreateBackBufferIfNeeded();
|
||||
+ else
|
||||
+ mBackBuffer = nullptr;
|
||||
qDeleteAll(copy);
|
||||
wl_event_queue_destroy(oldEventQueue);
|
||||
});
|
||||
@@ -183,11 +185,15 @@ QPaintDevice *QWaylandShmBackingStore::paintDevice()
|
||||
|
||||
void QWaylandShmBackingStore::updateDirtyStates(const QRegion ®ion)
|
||||
{
|
||||
- // Update dirty state of buffers based on what was painted. The back buffer will
|
||||
- // not be dirty since we already painted on it, while other buffers will become dirty.
|
||||
+ // Update dirty state of buffers based on what was painted. The back buffer will be
|
||||
+ // less dirty, since we painted to it, while other buffers will become more dirty.
|
||||
+ // This allows us to minimize copies between front and back buffers on swap in the
|
||||
+ // cases where the painted region overlaps with the previous frame (front buffer).
|
||||
for (QWaylandShmBuffer *b : std::as_const(mBuffers)) {
|
||||
if (b != mBackBuffer)
|
||||
b->dirtyRegion() += region;
|
||||
+ else
|
||||
+ b->dirtyRegion() -= region;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +204,7 @@ void QWaylandShmBackingStore::beginPaint(const QRegion ®ion)
|
||||
|
||||
const QMargins margins = windowDecorationMargins();
|
||||
const QRegion regionTranslated = region.translated(margins.left(), margins.top());
|
||||
- const bool bufferWasRecreated = recreateBackBufferIfNeeded(regionTranslated);
|
||||
+ const bool bufferWasRecreated = recreateBackBufferIfNeeded();
|
||||
updateDirtyStates(regionTranslated);
|
||||
|
||||
// Although undocumented, QBackingStore::beginPaint expects the painted region
|
||||
@@ -223,7 +229,7 @@ void QWaylandShmBackingStore::endPaint()
|
||||
// Inspired by QCALayerBackingStore.
|
||||
bool QWaylandShmBackingStore::scroll(const QRegion ®ion, int dx, int dy)
|
||||
{
|
||||
- if (!mBackBuffer)
|
||||
+ if (Q_UNLIKELY(!mBackBuffer || !mFrontBuffer))
|
||||
return false;
|
||||
|
||||
const qreal devicePixelRatio = waylandWindow()->scale();
|
||||
@@ -236,19 +242,35 @@ bool QWaylandShmBackingStore::scroll(const QRegion ®ion, int dx, int dy)
|
||||
|
||||
recreateBackBufferIfNeeded();
|
||||
|
||||
- QImage *backBufferImage = mBackBuffer->image();
|
||||
-
|
||||
const QPoint scrollDelta(dx, dy);
|
||||
const QMargins margins = windowDecorationMargins();
|
||||
const QRegion adjustedRegion = region.translated(margins.left(), margins.top());
|
||||
|
||||
- const QRect boundingRect = adjustedRegion.boundingRect();
|
||||
- const QPoint devicePixelDelta = scrollDelta * devicePixelRatio;
|
||||
+ const QRegion inPlaceRegion = adjustedRegion - mBackBuffer->dirtyRegion();
|
||||
+ const QRegion frontBufferRegion = adjustedRegion - inPlaceRegion;
|
||||
+
|
||||
+ if (!inPlaceRegion.isEmpty()) {
|
||||
+ const QRect inPlaceBoundingRect = inPlaceRegion.boundingRect();
|
||||
+ const QPoint devicePixelDelta = scrollDelta * devicePixelRatio;
|
||||
+
|
||||
+ qt_scrollRectInImage(*mBackBuffer->image(),
|
||||
+ QRect(inPlaceBoundingRect.topLeft() * devicePixelRatio,
|
||||
+ inPlaceBoundingRect.size() * devicePixelRatio),
|
||||
+ devicePixelDelta);
|
||||
+ }
|
||||
|
||||
- qt_scrollRectInImage(*backBufferImage,
|
||||
- QRect(boundingRect.topLeft() * devicePixelRatio,
|
||||
- boundingRect.size() * devicePixelRatio),
|
||||
- devicePixelDelta);
|
||||
+ if (!frontBufferRegion.isEmpty()) {
|
||||
+ QPainter painter(mBackBuffer->image());
|
||||
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
+ painter.scale(qreal(1) / devicePixelRatio, qreal(1) / devicePixelRatio);
|
||||
+ for (const QRect &rect : frontBufferRegion) {
|
||||
+ QRect sourceRect(rect.topLeft() * devicePixelRatio,
|
||||
+ rect.size() * devicePixelRatio);
|
||||
+ QRect destinationRect((rect.topLeft() + scrollDelta) * devicePixelRatio,
|
||||
+ rect.size() * devicePixelRatio);
|
||||
+ painter.drawImage(destinationRect, *mFrontBuffer->image(), sourceRect);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
// We do not mark the source region as dirty, even though it technically has "moved".
|
||||
// This matches the behavior of other backingstore implementations using qt_scrollRectInImage.
|
||||
@@ -289,6 +311,8 @@ void QWaylandShmBackingStore::flush(QWindow *window, const QRegion ®ion, cons
|
||||
if (windowDecoration() && windowDecoration()->isDirty())
|
||||
updateDecorations();
|
||||
|
||||
+ finalizeBackBuffer();
|
||||
+
|
||||
mFrontBuffer = mBackBuffer;
|
||||
|
||||
QMargins margins = windowDecorationMargins();
|
||||
@@ -313,6 +337,8 @@ QWaylandShmBuffer *QWaylandShmBackingStore::getBuffer(const QSize &size, bool &b
|
||||
mBuffers.removeAt(i);
|
||||
if (mBackBuffer == buffer)
|
||||
mBackBuffer = nullptr;
|
||||
+ if (mFrontBuffer == buffer)
|
||||
+ mFrontBuffer = nullptr;
|
||||
delete buffer;
|
||||
}
|
||||
}
|
||||
@@ -341,7 +367,7 @@ QWaylandShmBuffer *QWaylandShmBackingStore::getBuffer(const QSize &size, bool &b
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
-bool QWaylandShmBackingStore::recreateBackBufferIfNeeded(const QRegion &nonDirtyRegion)
|
||||
+bool QWaylandShmBackingStore::recreateBackBufferIfNeeded()
|
||||
{
|
||||
wl_display_dispatch_queue_pending(mDisplay->wl_display(), mEventQueue);
|
||||
|
||||
@@ -375,30 +401,6 @@ bool QWaylandShmBackingStore::recreateBackBufferIfNeeded(const QRegion &nonDirty
|
||||
qsizetype oldSizeInBytes = mBackBuffer ? mBackBuffer->image()->sizeInBytes() : 0;
|
||||
qsizetype newSizeInBytes = buffer->image()->sizeInBytes();
|
||||
|
||||
- // mBackBuffer may have been deleted here but if so it means its size was different so we wouldn't copy it anyway
|
||||
- if (mBackBuffer != buffer && oldSizeInBytes == newSizeInBytes) {
|
||||
- const QRegion clipRegion = buffer->dirtyRegion() - nonDirtyRegion;
|
||||
- const auto clipRects = clipRegion.rects();
|
||||
- if (!clipRects.empty()) {
|
||||
- Q_ASSERT(mBackBuffer);
|
||||
- const QImage *sourceImage = mBackBuffer->image();
|
||||
- QImage *targetImage = buffer->image();
|
||||
-
|
||||
- QPainter painter(targetImage);
|
||||
- painter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
- const qreal targetDevicePixelRatio = painter.device()->devicePixelRatio();
|
||||
- for (const QRect &clipRect : clipRects) { // Iterate clip rects, because complicated clip region causes higher CPU usage
|
||||
- if (clipRects.size() > 1)
|
||||
- painter.save();
|
||||
- painter.setClipRect(clipRect);
|
||||
- painter.scale(qreal(1) / targetDevicePixelRatio, qreal(1) / targetDevicePixelRatio);
|
||||
- painter.drawImage(QRectF(QPointF(), targetImage->size()), *sourceImage, sourceImage->rect());
|
||||
- if (clipRects.size() > 1)
|
||||
- painter.restore();
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
mBackBuffer = buffer;
|
||||
|
||||
for (QWaylandShmBuffer *buffer : std::as_const(mBuffers)) {
|
||||
@@ -412,11 +414,40 @@ bool QWaylandShmBackingStore::recreateBackBufferIfNeeded(const QRegion &nonDirty
|
||||
if (windowDecoration() && window()->isVisible() && oldSizeInBytes != newSizeInBytes)
|
||||
windowDecoration()->update();
|
||||
|
||||
- buffer->dirtyRegion() = QRegion();
|
||||
-
|
||||
return bufferWasRecreated;
|
||||
}
|
||||
|
||||
+void QWaylandShmBackingStore::finalizeBackBuffer()
|
||||
+{
|
||||
+ Q_ASSERT(mBackBuffer);
|
||||
+
|
||||
+ const QRegion clipRegion = mBackBuffer->dirtyRegion();
|
||||
+ if (clipRegion.isEmpty())
|
||||
+ return;
|
||||
+
|
||||
+ if (Q_UNLIKELY(!mFrontBuffer || mFrontBuffer == mBackBuffer))
|
||||
+ return;
|
||||
+
|
||||
+ const QImage *sourceImage = mFrontBuffer->image();
|
||||
+ QImage *targetImage = mBackBuffer->image();
|
||||
+
|
||||
+ QPainter painter(targetImage);
|
||||
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
+ const qreal targetDevicePixelRatio = painter.device()->devicePixelRatio();
|
||||
+ const auto clipRects = clipRegion.rects();
|
||||
+ for (const QRect &clipRect : clipRects) { // Iterate clip rects, because complicated clip region causes higher CPU usage
|
||||
+ if (clipRects.size() > 1)
|
||||
+ painter.save();
|
||||
+ painter.setClipRect(clipRect);
|
||||
+ painter.scale(qreal(1) / targetDevicePixelRatio, qreal(1) / targetDevicePixelRatio);
|
||||
+ painter.drawImage(QRectF(QPointF(), targetImage->size()), *sourceImage, sourceImage->rect());
|
||||
+ if (clipRects.size() > 1)
|
||||
+ painter.restore();
|
||||
+ }
|
||||
+
|
||||
+ mBackBuffer->dirtyRegion() = QRegion();
|
||||
+}
|
||||
+
|
||||
QImage *QWaylandShmBackingStore::entireSurface() const
|
||||
{
|
||||
return mBackBuffer->image();
|
||||
@@ -496,6 +527,8 @@ QImage QWaylandShmBackingStore::toImage() const
|
||||
// instead of flush() for widgets that have renderToTexture children
|
||||
// (QOpenGLWidget, QQuickWidget).
|
||||
|
||||
+ const_cast<QWaylandShmBackingStore *>(this)->finalizeBackBuffer();
|
||||
+
|
||||
return *contentSurface();
|
||||
}
|
||||
#endif // opengl
|
||||
diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h b/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h
|
||||
index efd80159e859..cfcafb283265 100644
|
||||
--- a/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h
|
||||
+++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h
|
||||
@@ -73,7 +73,8 @@ class Q_WAYLANDCLIENT_EXPORT QWaylandShmBackingStore : public QPlatformBackingSt
|
||||
QMargins windowDecorationMargins() const;
|
||||
QImage *entireSurface() const;
|
||||
QImage *contentSurface() const;
|
||||
- bool recreateBackBufferIfNeeded(const QRegion &nonDirtyRegion = QRegion());
|
||||
+ bool recreateBackBufferIfNeeded();
|
||||
+ void finalizeBackBuffer();
|
||||
|
||||
QWaylandWindow *waylandWindow() const;
|
||||
void iterateBuffer();
|
||||
2
sources
2
sources
|
|
@ -1 +1 @@
|
|||
SHA512 (qtbase-everywhere-src-6.8.2.tar.xz) = 4a074aca1c8bcca536fd428c969c0119f5131d0d52b67028edbb75a81dc6e0c15394f69e29cef513e6d8c6e93384cedc38dd03b0eed6ab1bbafbe2b5bbc85799
|
||||
SHA512 (qtbase-everywhere-src-6.10.1.tar.xz) = fd5dcdc59ec3b39e48563513ae438eb4540a28e72c46961295de2ccb08609289d477ef7e91aac0b8983f2d5b05b901b4f5be10eaca4ac4c6aa8cd598f37a228e
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue