From 489ef8091f17bb172622bbbcc8f58fcdfac1a5ba Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 19:55:46 -0400 Subject: [PATCH 001/113] ffmpeg: update to 6.0. --- common/shlibs | 26 +++++--- srcpkgs/ffmpeg/files/altivec.patch | 60 ------------------- .../patches/armv5tel-floating-point.patch | 18 ------ .../workaround-mesa-readeon-vaapi-bug.patch | 28 --------- srcpkgs/ffmpeg/template | 41 +++++-------- 5 files changed, 33 insertions(+), 140 deletions(-) delete mode 100644 srcpkgs/ffmpeg/files/altivec.patch delete mode 100644 srcpkgs/ffmpeg/patches/armv5tel-floating-point.patch delete mode 100644 srcpkgs/ffmpeg/patches/workaround-mesa-readeon-vaapi-bug.patch diff --git a/common/shlibs b/common/shlibs index 4e6a5a663fa0..a77346cce3e9 100644 --- a/common/shlibs +++ b/common/shlibs @@ -387,15 +387,23 @@ libid3tag.so.0 libid3tag-0.15.1b_1 libgif.so.7 giflib-5.1.0_1 libImlib2.so.1 imlib2-1.4.2_1 libmp3lame.so.0 lame-3.98.2_1 -libavdevice.so.58 libavdevice-4.0_1 -libavformat.so.58 libavformat-4.0_1 -libswscale.so.5 libswscale-4.0_1 -libswresample.so.3 libswresample-4.0_1 -libavresample.so.4 libavresample-4.0_1 -libpostproc.so.55 libpostproc-4.0_1 -libavcodec.so.58 libavcodec-4.0_1 -libavutil.so.56 libavutil-4.0_1 -libavfilter.so.7 libavfilter-4.0_1 +libavdevice.so.60 libavdevice-6.0_1 +libavformat.so.60 libavformat-6.0_1 +libswscale.so.7 libswscale-6.0_1 +libswresample.so.4 libswresample-6.0_1 +libpostproc.so.57 libpostproc-6.0_1 +libavcodec.so.60 libavcodec-6.0_1 +libavutil.so.58 libavutil-6.0_1 +libavfilter.so.9 libavfilter-6.0_1 +libavdevice.so.58 libavdevice4-4.0_1 +libavformat.so.58 libavformat4-4.0_1 +libswscale.so.5 libswscale4-4.0_1 +libswresample.so.3 libswresample4-4.0_1 +libavresample.so.4 libavresample4-4.0_1 +libpostproc.so.55 libpostproc4-4.0_1 +libavcodec.so.58 libavcodec4-4.0_1 +libavutil.so.56 libavutil4-4.0_1 +libavfilter.so.7 libavfilter4-4.0_1 libSDL-1.2.so.0 SDL-1.2.14_1 libSDL_image-1.2.so.0 SDL_image-1.2.10_1 libx264.so.157 x264-20190507.2245_1 diff --git a/srcpkgs/ffmpeg/files/altivec.patch b/srcpkgs/ffmpeg/files/altivec.patch deleted file mode 100644 index 9c5720046332..000000000000 --- a/srcpkgs/ffmpeg/files/altivec.patch +++ /dev/null @@ -1,60 +0,0 @@ -revert some altivec specific change on all ppc* except ppc64le* - -q66: "We should also throw in a revert of FFmpeg/FFmpeg@3a557c5 but only -conditionally, for ppc* but not ppc64le* (the new code is valid for -POWER8 VSX which LE targets as a baseline but not BE)" - - -This reverts commit 3a557c5d88b7b15b5954ba2743febb055549b536. ---- - libswscale/ppc/yuv2rgb_altivec.c | 24 ++++++++++++++++++++---- - 1 file changed, 20 insertions(+), 4 deletions(-) - -diff --git a/libswscale/ppc/yuv2rgb_altivec.c b/libswscale/ppc/yuv2rgb_altivec.c -index 536545293d..c1e2852adb 100644 ---- a/libswscale/ppc/yuv2rgb_altivec.c -+++ b/libswscale/ppc/yuv2rgb_altivec.c -@@ -305,6 +305,9 @@ static int altivec_ ## name(SwsContext *c, const unsigned char **in, \ - vector signed short R1, G1, B1; \ - vector unsigned char R, G, B; \ - \ -+ const vector unsigned char *y1ivP, *y2ivP, *uivP, *vivP; \ -+ vector unsigned char align_perm; \ -+ \ - vector signed short lCY = c->CY; \ - vector signed short lOY = c->OY; \ - vector signed short lCRV = c->CRV; \ -@@ -335,13 +338,26 @@ static int altivec_ ## name(SwsContext *c, const unsigned char **in, \ - vec_dstst(oute, (0x02000002 | (((w * 3 + 32) / 32) << 16)), 1); \ - \ - for (j = 0; j < w / 16; j++) { \ -- y0 = vec_xl(0, y1i); \ -+ y1ivP = (const vector unsigned char *) y1i; \ -+ y2ivP = (const vector unsigned char *) y2i; \ -+ uivP = (const vector unsigned char *) ui; \ -+ vivP = (const vector unsigned char *) vi; \ -+ \ -+ align_perm = vec_lvsl(0, y1i); \ -+ y0 = (vector unsigned char) \ -+ vec_perm(y1ivP[0], y1ivP[1], align_perm); \ - \ -- y1 = vec_xl(0, y2i); \ -+ align_perm = vec_lvsl(0, y2i); \ -+ y1 = (vector unsigned char) \ -+ vec_perm(y2ivP[0], y2ivP[1], align_perm); \ - \ -- u = (vector signed char) vec_xl(0, ui); \ -+ align_perm = vec_lvsl(0, ui); \ -+ u = (vector signed char) \ -+ vec_perm(uivP[0], uivP[1], align_perm); \ - \ -- v = (vector signed char) vec_xl(0, vi); \ -+ align_perm = vec_lvsl(0, vi); \ -+ v = (vector signed char) \ -+ vec_perm(vivP[0], vivP[1], align_perm); \ - \ - u = (vector signed char) \ - vec_sub(u, \ --- -2.27.0 - diff --git a/srcpkgs/ffmpeg/patches/armv5tel-floating-point.patch b/srcpkgs/ffmpeg/patches/armv5tel-floating-point.patch deleted file mode 100644 index 9a55178c74f0..000000000000 --- a/srcpkgs/ffmpeg/patches/armv5tel-floating-point.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/libavfilter/vf_drawtext.c 2017-10-26 21:03:03.000000000 +0200 -+++ b/libavfilter/vf_drawtext.c 2017-11-21 11:06:49.602284422 +0100 -@@ -39,6 +39,15 @@ - #endif - #include - -+#if (FE_ALL_EXCEPT == 0) -+/* E.g. ARM soft float does not define these */ -+#define FE_INVALID 0 -+#define FE_DIVBYZERO 0 -+#define FE_OVERFLOW 0 -+#define FE_UNDERFLOW 0 -+#define FE_INEXACT 0 -+#endif -+ - #if CONFIG_LIBFONTCONFIG - #include - #endif diff --git a/srcpkgs/ffmpeg/patches/workaround-mesa-readeon-vaapi-bug.patch b/srcpkgs/ffmpeg/patches/workaround-mesa-readeon-vaapi-bug.patch deleted file mode 100644 index 00e3f68a415b..000000000000 --- a/srcpkgs/ffmpeg/patches/workaround-mesa-readeon-vaapi-bug.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 811d290844206fc73dc39c3e5b67d5d895baedf8 Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Sat, 26 Jan 2019 19:48:35 +0100 -Subject: [PATCH] avcodec/vaapi_h264: skip decode if pic has no slices - -This fixes / workarounds https://bugs.freedesktop.org/show_bug.cgi?id=105368. -It was hit frequently when watching h264 channels received via DVB-X. -Corresponding kodi bug: https://github.com/xbmc/xbmc/issues/15704 ---- - libavcodec/vaapi_h264.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/libavcodec/vaapi_h264.c b/libavcodec/vaapi_h264.c -index 5854587a255..f12fdc457a4 100644 ---- a/libavcodec/vaapi_h264.c -+++ b/libavcodec/vaapi_h264.c -@@ -317,6 +317,11 @@ static int vaapi_h264_end_frame(AVCodecContext *avctx) - H264SliceContext *sl = &h->slice_ctx[0]; - int ret; - -+ if (pic->nb_slices == 0) { -+ ret = AVERROR_INVALIDDATA; -+ goto finish; -+ } -+ - ret = ff_vaapi_decode_issue(avctx, pic); - if (ret < 0) - goto finish; diff --git a/srcpkgs/ffmpeg/template b/srcpkgs/ffmpeg/template index aa058aab9ca9..a2c5d8750dd6 100644 --- a/srcpkgs/ffmpeg/template +++ b/srcpkgs/ffmpeg/template @@ -1,15 +1,14 @@ # Template file for 'ffmpeg' # audacity also needs to be bumped when a new ffmpeg version bumps libavformat's soname! -pkgname=ffmpeg -version=4.4.4 -revision=2 +version=6.0 +revision=1 short_desc="Decoding, encoding and streaming software" maintainer="Orphaned " license="GPL-3.0-or-later" homepage="https://www.ffmpeg.org" changelog="https://raw.githubusercontent.com/FFmpeg/FFmpeg/master/Changelog" distfiles="https://www.ffmpeg.org/releases/ffmpeg-${version}.tar.xz" -checksum=e80b380d595c809060f66f96a5d849511ef4a76a26b76eacf5778b94c3570309 +checksum=57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082 hostmakedepends="pkg-config perl" makedepends="zlib-devel bzip2-devel freetype-devel alsa-lib-devel libXfixes-devel @@ -26,12 +25,13 @@ makedepends="zlib-devel bzip2-devel freetype-devel alsa-lib-devel libXfixes-deve $(vopt_if webp libwebp-devel) $(vopt_if sofa libmysofa-devel) $(vopt_if drm libdrm-devel) $(vopt_if svtav1 libsvt-av1-devel) $(vopt_if srt srt-devel) $(vopt_if rist librist-devel) - $(vopt_if vulkan 'vulkan-loader Vulkan-Headers') + $(vopt_if vulkan 'vulkan-loader Vulkan-Headers Vulkan-Tools Vulkan-ValidationLayers') + $(vopt_if onevpl 'onevpl onevpl-devel') $(vopt_if nvenc nv-codec-headers) $(vopt_if nvdec nv-codec-headers)" depends="ffplay>=${version}_${revision}" build_options="x265 v4l2 vaapi vdpau vpx fdk_aac aom nvenc sndio pulseaudio - dav1d zimg webp sofa vulkan drm svtav1 srt rist nvdec" + dav1d zimg webp sofa vulkan drm svtav1 srt rist nvdec onevpl" build_options_default="x265 v4l2 vpx aom sndio pulseaudio dav1d webp vulkan drm srt rist" desc_option_srt="Enable support for SRT (Secure, Reliable, Transport)" desc_option_rist="Enable support for RIST (Reliable Internet Stream Transport)" @@ -39,10 +39,8 @@ desc_option_sofa="Enable support for AES SOFA" desc_option_webp="Enable support for WebP" case "$XBPS_TARGET_MACHINE" in - i686*|x86_64*) - hostmakedepends+=" nasm" - build_options_default+=" vaapi vdpau nvenc nvdec" - ;; + i686*) build_options_default+=" vaapi vdpau nvenc nvdec";; + x86_64*) build_options_default+=" vaapi vdpau nvenc nvdec onevpl";; ppc64*) build_options_default+=" vaapi vdpau";; mips*) CFLAGS="-mnan=legacy";; esac @@ -119,18 +117,19 @@ do_configure() { $(vopt_enable x265 libx265) \ $(vopt_enable v4l2 libv4l2) \ $(vopt_enable aom libaom) $(vopt_enable vaapi) $(vopt_enable vdpau) \ - --enable-libbs2b --enable-avresample --enable-libvidstab \ + --enable-libbs2b --enable-libvidstab \ $(vopt_enable dav1d libdav1d) \ $(vopt_enable zimg libzimg) \ $(vopt_enable webp libwebp) \ $(vopt_enable sofa libmysofa) \ $(vopt_enable vulkan) \ + $(vopt_enable onevpl libvpl) \ $(vopt_enable drm libdrm) \ $(vopt_enable svtav1 libsvtav1) \ $(vopt_enable srt libsrt) \ $(vopt_enable rist librist) \ - $(vopt_if nvenc '--enable-nvenc') \ - $(vopt_if nvdec '--enable-nvdec') + $(vopt_enable nvenc nvenc) \ + $(vopt_enable nvdec nvdec) } do_build() { @@ -157,10 +156,8 @@ libavdevice_package() { } libavresample_package() { - short_desc="FFmpeg audio resampling library" - pkg_install() { - vmove "usr/lib/libavresample.so.*" - } + short_desc="Package deprecated, removal needed" + build_style=meta } libavformat_package() { @@ -214,15 +211,9 @@ ffmpeg-devel_package() { libavfilter>=${version}_${revision} libpostproc>=${version}_${revision} libswscale>=${version}_${revision} - libswresample>=${version}_${revision} - libavresample>=${version}_${revision}" + libswresample>=${version}_${revision}" short_desc+=" - development files" - - if [ "$XBPS_TARGET_MACHINE" = "i686" ]; then - # /usr/bin/strip: error: the input file '/destdir//ffmpeg-devel-4.4.4/usr/lib/libavfilter.a(vf_atadenoise.o)' has no sections - nostrip_files="/usr/lib/libavfilter.a" - fi - + conflicts="ffmpeg4-devel" pkg_install() { vmove usr/include vmove usr/lib/pkgconfig From db20f06baaa6b1f7e6082dfb1a3dfb5f4bbc06d8 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 19:56:22 -0400 Subject: [PATCH 002/113] New package: ffmpeg4-4.4.4. --- srcpkgs/ffmpeg4-devel | 1 + srcpkgs/ffmpeg4/files/altivec.patch | 60 +++++ .../patches/armv5tel-floating-point.patch | 18 ++ ...h-libavcodec-libsvtav1-ten_bit_format.diff | 40 +++ .../workaround-mesa-readeon-vaapi-bug.patch | 28 ++ srcpkgs/ffmpeg4/template | 240 ++++++++++++++++++ srcpkgs/libavcodec4 | 1 + srcpkgs/libavdevice4 | 1 + srcpkgs/libavfilter4 | 1 + srcpkgs/libavformat4 | 1 + srcpkgs/libavresample4 | 1 + srcpkgs/libavutil4 | 1 + srcpkgs/libpostproc4 | 1 + srcpkgs/libswresample4 | 1 + srcpkgs/libswscale4 | 1 + 15 files changed, 396 insertions(+) create mode 120000 srcpkgs/ffmpeg4-devel create mode 100644 srcpkgs/ffmpeg4/files/altivec.patch create mode 100644 srcpkgs/ffmpeg4/patches/armv5tel-floating-point.patch create mode 100644 srcpkgs/ffmpeg4/patches/patch-libavcodec-libsvtav1-ten_bit_format.diff create mode 100644 srcpkgs/ffmpeg4/patches/workaround-mesa-readeon-vaapi-bug.patch create mode 100644 srcpkgs/ffmpeg4/template create mode 120000 srcpkgs/libavcodec4 create mode 120000 srcpkgs/libavdevice4 create mode 120000 srcpkgs/libavfilter4 create mode 120000 srcpkgs/libavformat4 create mode 120000 srcpkgs/libavresample4 create mode 120000 srcpkgs/libavutil4 create mode 120000 srcpkgs/libpostproc4 create mode 120000 srcpkgs/libswresample4 create mode 120000 srcpkgs/libswscale4 diff --git a/srcpkgs/ffmpeg4-devel b/srcpkgs/ffmpeg4-devel new file mode 120000 index 000000000000..887f354e7c6b --- /dev/null +++ b/srcpkgs/ffmpeg4-devel @@ -0,0 +1 @@ +ffmpeg4 \ No newline at end of file diff --git a/srcpkgs/ffmpeg4/files/altivec.patch b/srcpkgs/ffmpeg4/files/altivec.patch new file mode 100644 index 000000000000..9c5720046332 --- /dev/null +++ b/srcpkgs/ffmpeg4/files/altivec.patch @@ -0,0 +1,60 @@ +revert some altivec specific change on all ppc* except ppc64le* + +q66: "We should also throw in a revert of FFmpeg/FFmpeg@3a557c5 but only +conditionally, for ppc* but not ppc64le* (the new code is valid for +POWER8 VSX which LE targets as a baseline but not BE)" + + +This reverts commit 3a557c5d88b7b15b5954ba2743febb055549b536. +--- + libswscale/ppc/yuv2rgb_altivec.c | 24 ++++++++++++++++++++---- + 1 file changed, 20 insertions(+), 4 deletions(-) + +diff --git a/libswscale/ppc/yuv2rgb_altivec.c b/libswscale/ppc/yuv2rgb_altivec.c +index 536545293d..c1e2852adb 100644 +--- a/libswscale/ppc/yuv2rgb_altivec.c ++++ b/libswscale/ppc/yuv2rgb_altivec.c +@@ -305,6 +305,9 @@ static int altivec_ ## name(SwsContext *c, const unsigned char **in, \ + vector signed short R1, G1, B1; \ + vector unsigned char R, G, B; \ + \ ++ const vector unsigned char *y1ivP, *y2ivP, *uivP, *vivP; \ ++ vector unsigned char align_perm; \ ++ \ + vector signed short lCY = c->CY; \ + vector signed short lOY = c->OY; \ + vector signed short lCRV = c->CRV; \ +@@ -335,13 +338,26 @@ static int altivec_ ## name(SwsContext *c, const unsigned char **in, \ + vec_dstst(oute, (0x02000002 | (((w * 3 + 32) / 32) << 16)), 1); \ + \ + for (j = 0; j < w / 16; j++) { \ +- y0 = vec_xl(0, y1i); \ ++ y1ivP = (const vector unsigned char *) y1i; \ ++ y2ivP = (const vector unsigned char *) y2i; \ ++ uivP = (const vector unsigned char *) ui; \ ++ vivP = (const vector unsigned char *) vi; \ ++ \ ++ align_perm = vec_lvsl(0, y1i); \ ++ y0 = (vector unsigned char) \ ++ vec_perm(y1ivP[0], y1ivP[1], align_perm); \ + \ +- y1 = vec_xl(0, y2i); \ ++ align_perm = vec_lvsl(0, y2i); \ ++ y1 = (vector unsigned char) \ ++ vec_perm(y2ivP[0], y2ivP[1], align_perm); \ + \ +- u = (vector signed char) vec_xl(0, ui); \ ++ align_perm = vec_lvsl(0, ui); \ ++ u = (vector signed char) \ ++ vec_perm(uivP[0], uivP[1], align_perm); \ + \ +- v = (vector signed char) vec_xl(0, vi); \ ++ align_perm = vec_lvsl(0, vi); \ ++ v = (vector signed char) \ ++ vec_perm(vivP[0], vivP[1], align_perm); \ + \ + u = (vector signed char) \ + vec_sub(u, \ +-- +2.27.0 + diff --git a/srcpkgs/ffmpeg4/patches/armv5tel-floating-point.patch b/srcpkgs/ffmpeg4/patches/armv5tel-floating-point.patch new file mode 100644 index 000000000000..9a55178c74f0 --- /dev/null +++ b/srcpkgs/ffmpeg4/patches/armv5tel-floating-point.patch @@ -0,0 +1,18 @@ +--- a/libavfilter/vf_drawtext.c 2017-10-26 21:03:03.000000000 +0200 ++++ b/libavfilter/vf_drawtext.c 2017-11-21 11:06:49.602284422 +0100 +@@ -39,6 +39,15 @@ + #endif + #include + ++#if (FE_ALL_EXCEPT == 0) ++/* E.g. ARM soft float does not define these */ ++#define FE_INVALID 0 ++#define FE_DIVBYZERO 0 ++#define FE_OVERFLOW 0 ++#define FE_UNDERFLOW 0 ++#define FE_INEXACT 0 ++#endif ++ + #if CONFIG_LIBFONTCONFIG + #include + #endif diff --git a/srcpkgs/ffmpeg4/patches/patch-libavcodec-libsvtav1-ten_bit_format.diff b/srcpkgs/ffmpeg4/patches/patch-libavcodec-libsvtav1-ten_bit_format.diff new file mode 100644 index 000000000000..aa948f7a8a2d --- /dev/null +++ b/srcpkgs/ffmpeg4/patches/patch-libavcodec-libsvtav1-ten_bit_format.diff @@ -0,0 +1,40 @@ +#================================================================================================== +# From 031f1561cd286596cdb374da32f8aa816ce3b135 Mon Sep 17 00:00:00 2001 +# From: Christopher Degawa +# Date: Thu, 20 Oct 2022 22:55:27 -0500 +# Subject: [PATCH] avcodec/libsvtav1: remove compressed_ten_bit_format and simplify alloc_buffer +# +# compressed_ten_bit_format has been deprecated upstream and has no effect +# and can be removed. Plus, technically it was never used in the first place +# since it would require the app (ffmpeg) to set it and do additional +# processing of the input frames. +# +# Also simplify alloc_buffer by removing calculations relating to the non-existant processing. +# +# Signed-off-by: Christopher Degawa +#================================================================================================== +--- a/libavcodec/libsvtav1.c ++++ b/libavcodec/libsvtav1.c +@@ -124,16 +124,12 @@ static int svt_print_error(void *log_ctx, EbErrorType err, + + static int alloc_buffer(EbSvtAv1EncConfiguration *config, SvtContext *svt_enc) + { +- const int pack_mode_10bit = +- (config->encoder_bit_depth > 8) && (config->compressed_ten_bit_format == 0) ? 1 : 0; +- const size_t luma_size_8bit = +- config->source_width * config->source_height * (1 << pack_mode_10bit); +- const size_t luma_size_10bit = +- (config->encoder_bit_depth > 8 && pack_mode_10bit == 0) ? luma_size_8bit : 0; ++ const size_t luma_size = config->source_width * config->source_height * ++ (config->encoder_bit_depth > 8 ? 2 : 1); + + EbSvtIOFormat *in_data; + +- svt_enc->raw_size = (luma_size_8bit + luma_size_10bit) * 3 / 2; ++ svt_enc->raw_size = luma_size * 3 / 2; + + // allocate buffer for in and out + svt_enc->in_buf = av_mallocz(sizeof(*svt_enc->in_buf)); +-- +GitLab + diff --git a/srcpkgs/ffmpeg4/patches/workaround-mesa-readeon-vaapi-bug.patch b/srcpkgs/ffmpeg4/patches/workaround-mesa-readeon-vaapi-bug.patch new file mode 100644 index 000000000000..00e3f68a415b --- /dev/null +++ b/srcpkgs/ffmpeg4/patches/workaround-mesa-readeon-vaapi-bug.patch @@ -0,0 +1,28 @@ +From 811d290844206fc73dc39c3e5b67d5d895baedf8 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Sat, 26 Jan 2019 19:48:35 +0100 +Subject: [PATCH] avcodec/vaapi_h264: skip decode if pic has no slices + +This fixes / workarounds https://bugs.freedesktop.org/show_bug.cgi?id=105368. +It was hit frequently when watching h264 channels received via DVB-X. +Corresponding kodi bug: https://github.com/xbmc/xbmc/issues/15704 +--- + libavcodec/vaapi_h264.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/libavcodec/vaapi_h264.c b/libavcodec/vaapi_h264.c +index 5854587a255..f12fdc457a4 100644 +--- a/libavcodec/vaapi_h264.c ++++ b/libavcodec/vaapi_h264.c +@@ -317,6 +317,11 @@ static int vaapi_h264_end_frame(AVCodecContext *avctx) + H264SliceContext *sl = &h->slice_ctx[0]; + int ret; + ++ if (pic->nb_slices == 0) { ++ ret = AVERROR_INVALIDDATA; ++ goto finish; ++ } ++ + ret = ff_vaapi_decode_issue(avctx, pic); + if (ret < 0) + goto finish; diff --git a/srcpkgs/ffmpeg4/template b/srcpkgs/ffmpeg4/template new file mode 100644 index 000000000000..f2c851693d36 --- /dev/null +++ b/srcpkgs/ffmpeg4/template @@ -0,0 +1,240 @@ +# Template file for 'ffmpeg4' +# audacity also needs to be bumped when a new ffmpeg version bumps libavformat's soname! +pkgname=ffmpeg4 +version=4.4.4 +revision=1 +short_desc="Decoding, encoding and streaming software - ffmpeg4 libraries only" +maintainer="Orphaned " +license="GPL-3.0-or-later" +homepage="https://www.ffmpeg.org" +changelog="https://raw.githubusercontent.com/FFmpeg/FFmpeg/master/Changelog" +distfiles="https://www.ffmpeg.org/releases/ffmpeg-${version}.tar.xz" +checksum=e80b380d595c809060f66f96a5d849511ef4a76a26b76eacf5778b94c3570309 + +hostmakedepends="pkg-config perl" +makedepends="zlib-devel bzip2-devel freetype-devel alsa-lib-devel libXfixes-devel + libXext-devel libXvMC-devel libxcb-devel lame-devel libtheora-devel + libvorbis-devel x264-devel xvidcore-devel jack-devel SDL2-devel + libcdio-paranoia-devel librtmp-devel libmodplug-devel gnutls-devel + speex-devel celt-devel harfbuzz-devel libass-devel opus-devel ocl-icd-devel + libbs2b-devel libvidstab-devel vmaf-devel $(vopt_if pulseaudio pulseaudio-devel) + $(vopt_if vaapi libva-devel) $(vopt_if vdpau libvdpau-devel) + $(vopt_if x265 x265-devel) $(vopt_if v4l2 v4l-utils-devel) + $(vopt_if fdk_aac fdk-aac-devel) $(vopt_if vpx libvpx-devel) + $(vopt_if aom libaom-devel) $(vopt_if sndio sndio-devel) + $(vopt_if dav1d libdav1d-devel) $(vopt_if zimg zimg-devel) + $(vopt_if webp libwebp-devel) $(vopt_if sofa libmysofa-devel) + $(vopt_if drm libdrm-devel) $(vopt_if svtav1 libsvt-av1-devel) + $(vopt_if srt srt-devel) $(vopt_if rist librist-devel) + $(vopt_if vulkan 'vulkan-loader Vulkan-Headers') + $(vopt_if mfx 'libmfx libmfx-devel') + $(vopt_if nvenc nv-codec-headers) $(vopt_if nvdec nv-codec-headers)" + +build_options="x265 v4l2 vaapi vdpau vpx fdk_aac aom nvenc sndio pulseaudio + dav1d zimg webp sofa vulkan drm svtav1 srt rist nvdec mfx" +build_options_default="x265 v4l2 vpx aom sndio pulseaudio dav1d webp vulkan drm srt rist" + +desc_option_srt="Enable support for SRT (Secure, Reliable, Transport)" +desc_option_rist="Enable support for RIST (Reliable Internet Stream Transport)" +desc_option_sofa="Enable support for AES SOFA" +desc_option_webp="Enable support for WebP" + +case "$XBPS_TARGET_MACHINE" in + i686*) + hostmakedepends+=" nasm" + build_options_default+=" vaapi vdpau nvenc nvdec" + ;; + x86_64*) + hostmakedepends+=" nasm" + build_options_default+=" vaapi vdpau mfx nvenc nvdec" + ;; + ppc64*) build_options_default+=" vaapi vdpau";; + mips*) CFLAGS="-mnan=legacy";; +esac + +if [ "$XBPS_TARGET_WORDSIZE" != "32" ]; then + build_options_default+=" svtav1" +fi + +if [ "$XBPS_TARGET_NO_ATOMIC8" ]; then + makedepends+=" libatomic-devel" +fi + +_apply_patch() { + local args="$1" pname="$(basename $2)" + + if [ ! -f ".${pname}_done" ]; then + patch -N $args -i $2 + touch .${pname}_done + fi +} + +post_patch() { + case "$XBPS_TARGET_MACHINE" in + ppc64le*) ;; + ppc*) _apply_patch -p1 ${FILESDIR}/altivec.patch ;; + esac + + vsed -i libavfilter/vf_libvmaf.c -e 's!/usr/local/share/model/\(vmaf_v0.6.1\).pkl!/usr/share/vmaf/\1.json!' +} + +do_configure() { + # Fix gcc on x86_64-musl only + if [ "$XBPS_TARGET_MACHINE" = "x86_64-musl" ]; then + vsed -i configure -e "s;_cflags_speed='-O3';_cflags_speed='-O2';" + fi + + if [ "$CROSS_BUILD" ]; then + case "$XBPS_TARGET_MACHINE" in + arm*) _arch="arm";; + aarch64*) _arch="aarch64";; + mips*) _arch="mips";; + ppc64*) _arch="ppc64";; + ppc*) _arch="ppc";; + *) _arch="${XBPS_TARGET_MACHINE%%-musl}";; + esac + + _args+=" --enable-cross-compile + --sysroot=$XBPS_CROSS_BASE + --cross-prefix=${XBPS_CROSS_TRIPLET}- + --target-os=linux --arch=${_arch}" + fi + + case "$XBPS_TARGET_MACHINE" in + ppc|ppc-musl) _args+=" --disable-altivec";; + esac + + if [ "$XBPS_TARGET_NO_ATOMIC8" ]; then + _args+=" --extra-libs=-latomic" + fi + + ./configure --prefix=/usr --disable-debug --enable-gpl --enable-gnutls \ + --disable-stripping \ + --enable-libcdio --enable-version3 --enable-runtime-cpudetect \ + --enable-libmp3lame --enable-libvorbis --enable-libxvid \ + --enable-libx264 $(vopt_enable vpx libvpx) --enable-libtheora \ + --enable-shared --enable-static --enable-libxcb \ + $(vopt_enable pulseaudio libpulse) --enable-libfreetype --enable-libmodplug \ + --enable-libspeex --enable-libcelt --enable-libass \ + --enable-libopus --enable-librtmp --enable-libjack \ + $(vopt_if fdk_aac '--enable-nonfree --enable-libfdk-aac') \ + --disable-libopencore_amrnb --disable-libopencore_amrwb \ + --disable-libopenjpeg \ + --enable-postproc --enable-opencl ${_args} --enable-libvmaf ${_args} \ + $(vopt_enable x265 libx265) \ + $(vopt_enable v4l2 libv4l2) \ + $(vopt_enable aom libaom) $(vopt_enable vaapi) $(vopt_enable vdpau) \ + --enable-libbs2b --enable-avresample --enable-libvidstab \ + $(vopt_enable dav1d libdav1d) \ + $(vopt_enable zimg libzimg) \ + $(vopt_enable webp libwebp) \ + $(vopt_enable sofa libmysofa) \ + $(vopt_enable vulkan) \ + $(vopt_enable drm libdrm) \ + $(vopt_enable svtav1 libsvtav1) \ + $(vopt_enable srt libsrt) \ + $(vopt_enable rist librist) \ + $(vopt_enable mfx libmfx) \ + $(vopt_if nvenc '--enable-nvenc') \ + $(vopt_if nvdec '--enable-nvdec') +} + +do_build() { + make ${makejobs} + make doc/ff{mpeg,play}.1 +} + +do_install() { + make DESTDIR=${DESTDIR} install install-man + rm -rf ${DESTDIR}/usr/bin +} + +libavcodec4_package() { + short_desc="FFmpeg codec library" + pkg_install() { + vmove "usr/lib/libavcodec.so.*" + } +} + +libavdevice4_package() { + short_desc="FFmpeg device handling library" + pkg_install() { + vmove "usr/lib/libavdevice.so.*" + } +} + +libavresample4_package() { + short_desc="FFmpeg audio resampling library" + pkg_install() { + vmove "usr/lib/libavresample.so.*" + } +} + +libavformat4_package() { + short_desc="FFmpeg file format library" + pkg_install() { + vmove "usr/lib/libavformat.so.*" + } +} + +libavutil4_package() { + short_desc="FFmpeg utility library" + pkg_install() { + vmove "usr/lib/libavutil.so.*" + } +} + +libavfilter4_package() { + short_desc="FFmpeg audio/video filter library" + pkg_install() { + vmove "usr/lib/libavfilter.so.*" + } +} + +libpostproc4_package() { + short_desc="FFmpeg video postprocessing library" + pkg_install() { + vmove "usr/lib/libpostproc.so.*" + } +} + +libswscale4_package() { + short_desc="FFmpeg video scaling library" + pkg_install() { + vmove "usr/lib/libswscale.so.*" + } +} + +libswresample4_package() { + short_desc="FFmpeg video resampling library" + pkg_install() { + vmove "usr/lib/libswresample.so.*" + } +} + +ffmpeg4-devel_package() { + depends=" + libavcodec4>=${version}_${revision} + libavdevice4>=${version}_${revision} + libavformat4>=${version}_${revision} + libavutil4>=${version}_${revision} + libavfilter4>=${version}_${revision} + libpostproc4>=${version}_${revision} + libswscale4>=${version}_${revision} + libswresample4>=${version}_${revision} + libavresample4>=${version}_${revision}" + short_desc+=" - development files" + conflicts="ffmpeg-devel" + if [ "$XBPS_TARGET_MACHINE" = "i686" ]; then + # /usr/bin/strip: error: the input file '/destdir//ffmpeg-devel-4.4.4/usr/lib/libavfilter.a(vf_atadenoise.o)' has no sections + nostrip_files="/usr/lib/libavfilter.a" + fi + pkg_install() { + vmove usr/include + vmove usr/lib/pkgconfig + vmove "usr/lib/*.a" + vmove "usr/lib/*.so" + vmove usr/share/ffmpeg/examples + vmove usr/share/man/man3 + } +} diff --git a/srcpkgs/libavcodec4 b/srcpkgs/libavcodec4 new file mode 120000 index 000000000000..887f354e7c6b --- /dev/null +++ b/srcpkgs/libavcodec4 @@ -0,0 +1 @@ +ffmpeg4 \ No newline at end of file diff --git a/srcpkgs/libavdevice4 b/srcpkgs/libavdevice4 new file mode 120000 index 000000000000..887f354e7c6b --- /dev/null +++ b/srcpkgs/libavdevice4 @@ -0,0 +1 @@ +ffmpeg4 \ No newline at end of file diff --git a/srcpkgs/libavfilter4 b/srcpkgs/libavfilter4 new file mode 120000 index 000000000000..887f354e7c6b --- /dev/null +++ b/srcpkgs/libavfilter4 @@ -0,0 +1 @@ +ffmpeg4 \ No newline at end of file diff --git a/srcpkgs/libavformat4 b/srcpkgs/libavformat4 new file mode 120000 index 000000000000..887f354e7c6b --- /dev/null +++ b/srcpkgs/libavformat4 @@ -0,0 +1 @@ +ffmpeg4 \ No newline at end of file diff --git a/srcpkgs/libavresample4 b/srcpkgs/libavresample4 new file mode 120000 index 000000000000..887f354e7c6b --- /dev/null +++ b/srcpkgs/libavresample4 @@ -0,0 +1 @@ +ffmpeg4 \ No newline at end of file diff --git a/srcpkgs/libavutil4 b/srcpkgs/libavutil4 new file mode 120000 index 000000000000..887f354e7c6b --- /dev/null +++ b/srcpkgs/libavutil4 @@ -0,0 +1 @@ +ffmpeg4 \ No newline at end of file diff --git a/srcpkgs/libpostproc4 b/srcpkgs/libpostproc4 new file mode 120000 index 000000000000..887f354e7c6b --- /dev/null +++ b/srcpkgs/libpostproc4 @@ -0,0 +1 @@ +ffmpeg4 \ No newline at end of file diff --git a/srcpkgs/libswresample4 b/srcpkgs/libswresample4 new file mode 120000 index 000000000000..887f354e7c6b --- /dev/null +++ b/srcpkgs/libswresample4 @@ -0,0 +1 @@ +ffmpeg4 \ No newline at end of file diff --git a/srcpkgs/libswscale4 b/srcpkgs/libswscale4 new file mode 120000 index 000000000000..887f354e7c6b --- /dev/null +++ b/srcpkgs/libswscale4 @@ -0,0 +1 @@ +ffmpeg4 \ No newline at end of file From e75857aa8f399eefafe80bbec35898dd08f40abd Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 19:59:04 -0400 Subject: [PATCH 003/113] opencv: update to 4.7.0. --- common/shlibs | 104 ++++++++++++++++++++-------------------- srcpkgs/opencv/template | 8 ++-- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/common/shlibs b/common/shlibs index a77346cce3e9..ca0ee066215e 100644 --- a/common/shlibs +++ b/common/shlibs @@ -2136,58 +2136,58 @@ libcapstone.so.4 capstone-4.0_1 libhavege.so.2 libhaveged-1.9.11_1 libnih.so.1 libnih-1.0.3_1 libnih-dbus.so.1 libnih-1.0.3_1 -libopencv_quality.so.406 libopencv-4.6.0_1 -libopencv_reg.so.406 libopencv-4.6.0_1 -libopencv_surface_matching.so.406 libopencv-4.6.0_1 -libopencv_xphoto.so.406 libopencv-4.6.0_1 -libopencv_freetype.so.406 libopencv-4.6.0_1 -libopencv_fuzzy.so.406 libopencv-4.6.0_1 -libopencv_hfs.so.406 libopencv-4.6.0_1 -libopencv_img_hash.so.406 libopencv-4.6.0_1 -libopencv_line_descriptor.so.406 libopencv-4.6.0_1 -libopencv_saliency.so.406 libopencv-4.6.0_1 -libopencv_structured_light.so.406 libopencv-4.6.0_1 -libopencv_aruco.so.406 libopencv-4.6.0_1 -libopencv_bgsegm.so.406 libopencv-4.6.0_1 -libopencv_bioinspired.so.406 libopencv-4.6.0_1 -libopencv_ccalib.so.406 libopencv-4.6.0_1 -libopencv_face.so.406 libopencv-4.6.0_1 -libopencv_tracking.so.406 libopencv-4.6.0_1 -libopencv_xfeatures2d.so.406 libopencv-4.6.0_1 -libopencv_optflow.so.406 libopencv-4.6.0_1 -libopencv_ximgproc.so.406 libopencv-4.6.0_1 -libopencv_plot.so.406 libopencv-4.6.0_1 -libopencv_text.so.406 libopencv-4.6.0_1 -libopencv_ml.so.406 libopencv-4.6.0_1 -libopencv_objdetect.so.406 libopencv-4.6.0_1 -libopencv_dnn.so.406 libopencv-4.6.0_1 -libopencv_shape.so.406 libopencv-4.6.0_1 -libopencv_stitching.so.406 libopencv-4.6.0_1 -libopencv_photo.so.406 libopencv-4.6.0_1 -libopencv_video.so.406 libopencv-4.6.0_1 -libopencv_calib3d.so.406 libopencv-4.6.0_1 -libopencv_features2d.so.406 libopencv-4.6.0_1 -libopencv_flann.so.406 libopencv-4.6.0_1 -libopencv_highgui.so.406 libopencv-4.6.0_1 -libopencv_videoio.so.406 libopencv-4.6.0_1 -libopencv_imgcodecs.so.406 libopencv-4.6.0_1 -libopencv_imgproc.so.406 libopencv-4.6.0_1 -libopencv_core.so.406 libopencv-4.6.0_1 -libopencv_superres.so.406 libopencv-4.6.0_1 -libopencv_videostab.so.406 libopencv-4.6.0_1 -libopencv_gapi.so.406 libopencv-4.6.0_1 -libopencv_xobjdetect.so.406 libopencv-4.6.0_1 -libopencv_datasets.so.406 libopencv-4.6.0_1 -libopencv_dnn_objdetect.so.406 libopencv-4.6.0_1 -libopencv_dnn_superres.so.406 libopencv-4.6.0_1 -libopencv_dpm.so.406 libopencv-4.6.0_1 -libopencv_phase_unwrapping.so.406 libopencv-4.6.0_1 -libopencv_stereo.so.406 libopencv-4.6.0_1 -libopencv_rapid.so.406 libopencv-4.6.0_1 -libopencv_intensity_transform.so.406 libopencv-4.6.0_1 -libopencv_alphamat.so.406 libopencv-4.6.0_1 -libopencv_barcode.so.406 libopencv-4.6.0_1 -libopencv_mcc.so.406 libopencv-4.6.0_1 +libopencv_quality.so.407 libopencv-4.7.0_1 +libopencv_reg.so.407 libopencv-4.7.0_1 +libopencv_surface_matching.so.407 libopencv-4.7.0_1 +libopencv_xphoto.so.407 libopencv-4.7.0_1 +libopencv_freetype.so.407 libopencv-4.7.0_1 +libopencv_fuzzy.so.407 libopencv-4.7.0_1 +libopencv_hfs.so.407 libopencv-4.7.0_1 +libopencv_img_hash.so.407 libopencv-4.7.0_1 +libopencv_line_descriptor.so.407 libopencv-4.7.0_1 +libopencv_saliency.so.407 libopencv-4.7.0_1 +libopencv_structured_light.so.407 libopencv-4.7.0_1 +libopencv_aruco.so.407 libopencv-4.7.0_1 +libopencv_bgsegm.so.407 libopencv-4.7.0_1 +libopencv_bioinspired.so.407 libopencv-4.7.0_1 +libopencv_ccalib.so.407 libopencv-4.7.0_1 +libopencv_face.so.407 libopencv-4.7.0_1 +libopencv_tracking.so.407 libopencv-4.7.0_1 +libopencv_xfeatures2d.so.407 libopencv-4.7.0_1 +libopencv_optflow.so.407 libopencv-4.7.0_1 +libopencv_ximgproc.so.407 libopencv-4.7.0_1 +libopencv_plot.so.407 libopencv-4.7.0_1 +libopencv_text.so.407 libopencv-4.7.0_1 +libopencv_ml.so.407 libopencv-4.7.0_1 +libopencv_objdetect.so.407 libopencv-4.7.0_1 +libopencv_dnn.so.407 libopencv-4.7.0_1 +libopencv_shape.so.407 libopencv-4.7.0_1 +libopencv_stitching.so.407 libopencv-4.7.0_1 +libopencv_photo.so.407 libopencv-4.7.0_1 +libopencv_video.so.407 libopencv-4.7.0_1 +libopencv_calib3d.so.407 libopencv-4.7.0_1 +libopencv_features2d.so.407 libopencv-4.7.0_1 +libopencv_flann.so.407 libopencv-4.7.0_1 +libopencv_highgui.so.407 libopencv-4.7.0_1 +libopencv_videoio.so.407 libopencv-4.7.0_1 +libopencv_imgcodecs.so.407 libopencv-4.7.0_1 +libopencv_imgproc.so.407 libopencv-4.7.0_1 +libopencv_core.so.407 libopencv-4.7.0_1 +libopencv_superres.so.407 libopencv-4.7.0_1 +libopencv_videostab.so.407 libopencv-4.7.0_1 +libopencv_gapi.so.407 libopencv-4.7.0_1 +libopencv_xobjdetect.so.407 libopencv-4.7.0_1 +libopencv_datasets.so.407 libopencv-4.7.0_1 +libopencv_dnn_objdetect.so.407 libopencv-4.7.0_1 +libopencv_dnn_superres.so.407 libopencv-4.7.0_1 +libopencv_dpm.so.407 libopencv-4.7.0_1 +libopencv_phase_unwrapping.so.407 libopencv-4.7.0_1 +libopencv_stereo.so.407 libopencv-4.7.0_1 +libopencv_rapid.so.407 libopencv-4.7.0_1 +libopencv_intensity_transform.so.407 libopencv-4.7.0_1 +libopencv_alphamat.so.407 libopencv-4.7.0_1 +libopencv_barcode.so.407 libopencv-4.7.0_1 +libopencv_mcc.so.407 libopencv-4.7.0_1 libuniconf.so.4.6 wvstreams-4.6.1_20 libwvbase.so.4.6 wvstreams-4.6.1_20 libwvutils.so.4.6 wvstreams-4.6.1_20 diff --git a/srcpkgs/opencv/template b/srcpkgs/opencv/template index 69c635b1ad2b..41f3183f1582 100644 --- a/srcpkgs/opencv/template +++ b/srcpkgs/opencv/template @@ -1,7 +1,7 @@ # Template file for 'opencv' pkgname=opencv -version=4.6.0 -revision=4 +version=4.7.0 +revision=1 create_wrksrc=yes build_wrksrc=${pkgname}-${version} build_style=cmake @@ -24,8 +24,8 @@ homepage="https://opencv.org" changelog="https://github.com/opencv/opencv/wiki/ChangeLog" distfiles="https://github.com/opencv/opencv/archive/${version}.tar.gz https://github.com/opencv/opencv_contrib/archive/${version}.tar.gz>contrib.tar.gz" -checksum="1ec1cba65f9f20fe5a41fda1586e01c70ea0c9a6d7b67c9e13edf0cfe2239277 - 1777d5fd2b59029cf537e5fd6f8aa68d707075822f90bde683fcde086f85f7a7" +checksum="8df0079cdbe179748a18d44731af62a245a45ebf5085223dc03133954c662973 + 42df840cf9055e59d0e22c249cfb19f04743e1bdad113d31b1573d3934d62584" patch_args="-Np1 -d ${build_wrksrc}" # tests hang indenfinitely, even with test data included make_check=no From 872b27ccab83f6e66524d8e6d365e407679da160 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 19:59:45 -0400 Subject: [PATCH 004/113] actiona: revbump for opencv-4.7.0 --- srcpkgs/actiona/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/actiona/template b/srcpkgs/actiona/template index cf5f0b7a2ae6..0d899311e6df 100644 --- a/srcpkgs/actiona/template +++ b/srcpkgs/actiona/template @@ -1,7 +1,7 @@ # Template file for 'actiona' pkgname=actiona version=3.10.1 -revision=2 +revision=3 build_style=qmake configure_args="PKGCONFIG_OPENCV=opencv4" hostmakedepends="pkg-config qt5-plugin-mysql qt5-qmake qt5-host-tools" From 1d72e9120877fdcfdb9ec558b59432aade245e5a Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 19:59:46 -0400 Subject: [PATCH 005/113] qimgv: revbump for opencv-4.7.0 --- srcpkgs/qimgv/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/qimgv/template b/srcpkgs/qimgv/template index 7eb30db33992..dd341dfe1bfc 100644 --- a/srcpkgs/qimgv/template +++ b/srcpkgs/qimgv/template @@ -1,7 +1,7 @@ # Template file for 'qimgv' pkgname=qimgv version=1.0.2 -revision=2 +revision=3 build_style=cmake configure_args="$(vopt_if video -DVIDEO_SUPPORT=ON -DVIDEO_SUPPORT=OFF) $(vopt_if scale -DOPENCV_SUPPORT=ON -DOPENCV_SUPPORT=OFF) From a3ddd74e30609df762cdd4da69b413abb689ba87 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 19:59:46 -0400 Subject: [PATCH 006/113] retroshare: revbump for opencv-4.7.0 --- srcpkgs/retroshare/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/retroshare/template b/srcpkgs/retroshare/template index 8a0786c21a08..72023fa98b75 100644 --- a/srcpkgs/retroshare/template +++ b/srcpkgs/retroshare/template @@ -1,7 +1,7 @@ # Template file for 'retroshare' pkgname=retroshare version=0.6.6 -revision=2 +revision=4 build_style=qmake #XXX broadcast feature requires an ancient udp-discovery-cpp which either needs # to be fetched+patched (FTBFS) here or packaged :/ From f5cd3b08b3f16c62be3ca0b5f7ced3bc983a38f2 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 19:59:46 -0400 Subject: [PATCH 007/113] waifu2x-converter-cpp: revbump for opencv-4.7.0 --- srcpkgs/waifu2x-converter-cpp/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/waifu2x-converter-cpp/template b/srcpkgs/waifu2x-converter-cpp/template index 8c095d0d7bab..aa52d8c981a8 100644 --- a/srcpkgs/waifu2x-converter-cpp/template +++ b/srcpkgs/waifu2x-converter-cpp/template @@ -1,7 +1,7 @@ # Template file for 'waifu2x-converter-cpp' pkgname=waifu2x-converter-cpp version=5.2.4 -revision=2 +revision=3 build_style=cmake configure_args="-DINSTALL_MODELS=ON" hostmakedepends="pkg-config" From f0da174a70814736f7dc4213b013fdbbb82e6d01 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:00:38 -0400 Subject: [PATCH 008/113] vlc: revbump for ffmpeg4-4.4.3 --- srcpkgs/vlc/template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srcpkgs/vlc/template b/srcpkgs/vlc/template index 210762b0a7e2..855ca5238662 100644 --- a/srcpkgs/vlc/template +++ b/srcpkgs/vlc/template @@ -1,7 +1,7 @@ # Template file for 'vlc' pkgname=vlc version=3.0.18 -revision=3 +revision=4 build_style=gnu-configure configure_args="--disable-gme --disable-libtar --enable-jack --enable-live555 --disable-fluidsynth --enable-dvdread @@ -25,7 +25,7 @@ lib32disabled=yes hostmakedepends="automake libtool pkg-config flex gettext libgcrypt-devel live555-devel gettext-devel $(vopt_if lua lua52) $(vopt_if chromecast protobuf)" makedepends=" - avahi-libs-devel dbus-glib-devel faad2-devel ffmpeg-devel freefont-ttf + avahi-libs-devel dbus-glib-devel faad2-devel ffmpeg4-devel freefont-ttf gnutls-devel jack-devel liba52-devel libass-devel libbluray-devel libcdio-devel libdca-devel libdvbpsi-devel libdvdnav-devel libmad-devel libmatroska-devel libmodplug-devel libmpcdec-devel libmpeg2-devel From 7ebea9d5668edb8bc1c65505ff52422cfe4d31b4 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:00:55 -0400 Subject: [PATCH 009/113] osg: revbump for ffmpeg4-4.4.3 --- srcpkgs/osg/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/osg/template b/srcpkgs/osg/template index a9ebbd287933..755793f7e11b 100644 --- a/srcpkgs/osg/template +++ b/srcpkgs/osg/template @@ -8,7 +8,7 @@ build_helper="qemu" configure_args="-DLIB_POSTFIX=" hostmakedepends="pkg-config xrandr" makedepends="MesaLib-devel gtkglext-devel libcurl-devel giflib-devel librsvg-devel - jasper-devel tiff-devel libgdal-devel libgta-devel ffmpeg-devel xine-lib-devel + jasper-devel tiff-devel libgdal-devel libgta-devel ffmpeg4-devel xine-lib-devel SDL2-devel gst-plugins-base1-devel $(vopt_if openexr libopenexr-devel) $(vopt_if poppler poppler-glib-devel) From 799c48913dbc1fe40841121c7f6912d61c088118 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:13 -0400 Subject: [PATCH 010/113] xine-lib: revbump for ffmpeg4-4.4.3 --- srcpkgs/xine-lib/template | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/srcpkgs/xine-lib/template b/srcpkgs/xine-lib/template index f713eff49b07..ed6194c17d11 100644 --- a/srcpkgs/xine-lib/template +++ b/srcpkgs/xine-lib/template @@ -1,6 +1,6 @@ # Template file for 'xine-lib' pkgname=xine-lib -version=1.2.12 +version=1.2.13 revision=1 build_style=gnu-configure configure_args="--disable-vcd --disable-gnomevfs --without-esound --disable-dxr3 @@ -8,7 +8,7 @@ configure_args="--disable-vcd --disable-gnomevfs --without-esound --disable-dxr3 hostmakedepends="automake gettext-devel libtool pkg-config perl" makedepends=" zlib-devel alsa-lib-devel libxcb-devel libSM-devel libXext-devel libXv-devel - libXvMC-devel liba52-devel libmad-devel ffmpeg-devel pulseaudio-devel + libXvMC-devel liba52-devel libmad-devel ffmpeg4-devel pulseaudio-devel jack-devel samba-devel libflac-devel libmodplug-devel libmpcdec-devel speex-devel libtheora-devel libvorbis-devel libdca-devel faad2-devel libcdio-devel libbluray-devel aalib-devel libcaca-devel libXinerama-devel @@ -19,7 +19,7 @@ license="GPL-2.0-or-later, LGPL-2.0-or-later" homepage="http://www.xine-project.org" changelog="https://sourceforge.net/projects/xine/files/xine-lib/${version}/README.txt/view" distfiles="${SOURCEFORGE_SITE}/xine/${pkgname}-${version}.tar.xz" -checksum=d606270468e1540c2a89c0d7f5fdf11e17ecc0c2698cc0bcb1065ff26abee098 +checksum=5f10d6d718a4a51c17ed1b32b031d4f9b80b061e8276535b2be31e5ac4b75e6f case "$XBPS_TARGET_MACHINE" in i686-musl) From 6a08a4dd48e7ad6a4177446f465398f928c64ecf Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:45 -0400 Subject: [PATCH 011/113] QMPlay2: revbump for ffmpeg-6.0 --- srcpkgs/QMPlay2/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/QMPlay2/template b/srcpkgs/QMPlay2/template index 850df9d418b9..8d2ce7a76156 100644 --- a/srcpkgs/QMPlay2/template +++ b/srcpkgs/QMPlay2/template @@ -1,7 +1,7 @@ # Template file for 'QMPlay2' pkgname=QMPlay2 version=23.06.17 -revision=1 +revision=2 build_style=cmake hostmakedepends="pkg-config qt5-qmake qt5-host-tools" makedepends="alsa-lib-devel ffmpeg-devel libass-devel libcdio-devel libgme-devel From 2b6b3567ae402780c7e7cb58e26ccb66e72c5295 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:45 -0400 Subject: [PATCH 012/113] alsa-plugins: revbump for ffmpeg-6.0 --- srcpkgs/alsa-plugins/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/alsa-plugins/template b/srcpkgs/alsa-plugins/template index 0bfa6d9fd264..a5708a7d82a8 100644 --- a/srcpkgs/alsa-plugins/template +++ b/srcpkgs/alsa-plugins/template @@ -1,7 +1,7 @@ # Template file for 'alsa-plugins' pkgname=alsa-plugins version=1.2.7.1 -revision=1 +revision=2 build_style=gnu-configure configure_args="--disable-maemo-plugin" hostmakedepends="pkg-config" From f8340f2ff564bc87ac5df4e412086925af1689a7 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:45 -0400 Subject: [PATCH 013/113] arcan: revbump for ffmpeg-6.0 --- srcpkgs/arcan/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/arcan/template b/srcpkgs/arcan/template index 7be9652eccf3..ccc7df11ceac 100644 --- a/srcpkgs/arcan/template +++ b/srcpkgs/arcan/template @@ -2,7 +2,7 @@ # !! keep synced with: acfgfs aclip aloadimage pkgname=arcan version=0.6.2.1 -revision=1 +revision=2 create_wrksrc=yes build_wrksrc=arcan/src build_style=cmake From 36c05299730aa27031a0146a33a0b4144cf4ce1f Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:45 -0400 Subject: [PATCH 014/113] attract: revbump for ffmpeg4-4.4.3 --- srcpkgs/attract/template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srcpkgs/attract/template b/srcpkgs/attract/template index 26144e931a3c..e760bf0d18ae 100644 --- a/srcpkgs/attract/template +++ b/srcpkgs/attract/template @@ -1,12 +1,12 @@ # Template file for 'attract' pkgname=attract version=2.6.2 -revision=1 +revision=2 build_style=gnu-makefile make_build_args="VERBOSE=1" make_use_env=yes hostmakedepends="pkg-config" -makedepends="SFML-devel ffmpeg-devel fontconfig-devel glu-devel libarchive-devel +makedepends="SFML-devel ffmpeg4-devel fontconfig-devel glu-devel libarchive-devel libcurl-devel libjpeg-turbo-devel xine-lib rapidjson libXrandr-devel" depends="git" short_desc="Attract-Mode is a graphical frontend for emulators" From 500e6d6beae4fd96fe97ab0c5ce5b50f11f728db Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:45 -0400 Subject: [PATCH 015/113] aubio: revbump for ffmpeg-6.0 --- srcpkgs/aubio/patches/ffmpeg5.patch | 25 +++++++++++++++++++++++++ srcpkgs/aubio/template | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 srcpkgs/aubio/patches/ffmpeg5.patch diff --git a/srcpkgs/aubio/patches/ffmpeg5.patch b/srcpkgs/aubio/patches/ffmpeg5.patch new file mode 100644 index 000000000000..aace41a6e6d9 --- /dev/null +++ b/srcpkgs/aubio/patches/ffmpeg5.patch @@ -0,0 +1,25 @@ +From 8a05420e5dd8c7b8b2447f82dc919765876511b3 Mon Sep 17 00:00:00 2001 +From: Paul Brossier +Date: Tue, 25 Jan 2022 18:30:27 +0100 +Subject: [PATCH] [source_avcodec] define FF_API_LAVF_AVCTX for libavcodec > + 59, thx @berolinux (closes gh-353) + +--- + src/io/source_avcodec.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/io/source_avcodec.c b/src/io/source_avcodec.c +index e0ae93b5..1421bd9a 100644 +--- a/src/io/source_avcodec.c ++++ b/src/io/source_avcodec.c +@@ -68,6 +68,10 @@ + #define AUBIO_AVCODEC_MAX_BUFFER_SIZE AV_INPUT_BUFFER_MIN_SIZE + #endif + ++#if LIBAVCODEC_VERSION_MAJOR >= 59 ++#define FF_API_LAVF_AVCTX 1 ++#endif ++ + struct _aubio_source_avcodec_t { + uint_t hop_size; + uint_t samplerate; diff --git a/srcpkgs/aubio/template b/srcpkgs/aubio/template index ad1c4b256991..7d875cc02541 100644 --- a/srcpkgs/aubio/template +++ b/srcpkgs/aubio/template @@ -1,7 +1,7 @@ # Template file for 'aubio' pkgname=aubio version=0.4.9 -revision=1 +revision=2 build_style=waf3 # XXX lash, pure and swig support. hostmakedepends="pkg-config txt2man" From ed5c31130978eb0a1ca265ca07d073c46327dbb7 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:45 -0400 Subject: [PATCH 016/113] audacious-plugins: revbump for ffmpeg-6.0 --- .../audacious-plugins/patches/ffmpeg5.patch | 43 +++++++++++++++++++ srcpkgs/audacious-plugins/template | 2 +- 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 srcpkgs/audacious-plugins/patches/ffmpeg5.patch diff --git a/srcpkgs/audacious-plugins/patches/ffmpeg5.patch b/srcpkgs/audacious-plugins/patches/ffmpeg5.patch new file mode 100644 index 000000000000..4e5e34099d71 --- /dev/null +++ b/srcpkgs/audacious-plugins/patches/ffmpeg5.patch @@ -0,0 +1,43 @@ +commit 298aa371c56c2f52c25a33d9bdec4918b11cebdc +Author: tibequadorian +Date: Sat Mar 19 18:40:12 2022 +0100 + + audacious-plugins: rebuild against ffmpeg-5.0 + +diff --git a/srcpkgs/audacious-plugins/patches/ffmpeg-5.0.patch b/srcpkgs/audacious-plugins/patches/ffmpeg-5.0.patch +new file mode 100644 +index 0000000000..617c11215b +--- /dev/null ++++ b/srcpkgs/audacious-plugins/patches/ffmpeg-5.0.patch +@@ -0,0 +1,31 @@ ++From f60beb400eeb1e4778bbfd738bc4a4ccef3de539 Mon Sep 17 00:00:00 2001 ++From: John Lindgren ++Date: Sat, 5 Mar 2022 12:05:34 -0500 ++Subject: [PATCH] Fix build with FFmpeg 5.0 ++ ++--- ++ src/ffaudio/ffaudio-core.cc | 4 ++-- ++ 1 file changed, 2 insertions(+), 2 deletions(-) ++ ++diff --git a/src/ffaudio/ffaudio-core.cc b/src/ffaudio/ffaudio-core.cc ++index 16dc63e3a..a2b95fd6c 100644 ++--- a/src/ffaudio/ffaudio-core.cc +++++ b/src/ffaudio/ffaudio-core.cc ++@@ -274,7 +274,7 @@ static AVInputFormat * get_format_by_content (const char * name, VFSFile & file) ++ AVProbeData d = {name, buf, filled}; ++ score = target; ++ ++- f = av_probe_input_format2 (& d, true, & score); +++ f = (AVInputFormat *) av_probe_input_format2 (& d, true, & score); ++ if (f) ++ break; ++ ++@@ -347,7 +347,7 @@ static bool find_codec (AVFormatContext * c, CodecInfo * cinfo) ++ #endif ++ if (stream && stream->codecpar && stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) ++ { ++- AVCodec * codec = avcodec_find_decoder (stream->codecpar->codec_id); +++ AVCodec * codec = (AVCodec *) avcodec_find_decoder (stream->codecpar->codec_id); ++ ++ if (codec) ++ { diff --git a/srcpkgs/audacious-plugins/template b/srcpkgs/audacious-plugins/template index 88cbc1671fc6..beebfae59ed4 100644 --- a/srcpkgs/audacious-plugins/template +++ b/srcpkgs/audacious-plugins/template @@ -2,7 +2,7 @@ #Keep in sync with audacious! pkgname=audacious-plugins version=4.3.1 -revision=1 +revision=2 build_style=meson configure_args="$(vopt_bool gtk3 gtk) $(vopt_bool gtk3) $(vopt_bool qt) $(vopt_bool qt qt6)" From 31d7a3bb1afd1f01897079f4fe21c358de65e0ef Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:45 -0400 Subject: [PATCH 017/113] audacity: revbump for ffmpeg4-4.4.3 --- srcpkgs/audacity/template | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/srcpkgs/audacity/template b/srcpkgs/audacity/template index d509c0a89407..11e20255685b 100644 --- a/srcpkgs/audacity/template +++ b/srcpkgs/audacity/template @@ -1,7 +1,7 @@ # Template file for 'audacity' pkgname=audacity version=2.4.1 -revision=2 +revision=3 build_style=gnu-configure configure_args="--with-ffmpeg=system --with-libsndfile=system --with-expat=system --with-libsoxr=system --with-lame=system --with-lv2=system ac_cv_path_WX_CONFIG=wx-config-gtk3" @@ -9,7 +9,7 @@ hostmakedepends="pkg-config cmake gettext libtool m4 which" makedepends="jack-devel wxWidgets-gtk3-devel gtk+3-devel libmad-devel soundtouch-devel libsoxr-devel vamp-plugin-sdk-devel lame-devel libid3tag-devel libflac-devel - ffmpeg-devel twolame-devel serd-devel lv2 lilv-devel suil-devel" + ffmpeg4-devel twolame-devel serd-devel lv2 lilv-devel suil-devel" depends="desktop-file-utils hicolor-icon-theme" short_desc="Graphical cross-platform audio editor" maintainer="Orphaned " @@ -33,5 +33,4 @@ post_install() { vcopy plug-ins /usr/share/audacity rm ${DESTDIR}/usr/share/doc/audacity/LICENSE.txt - vlicense LICENSE.txt LICENSE } From 10ade9d793594c3a5985bda6736712dc10ef4d0e Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:45 -0400 Subject: [PATCH 018/113] avidemux: revbump for ffmpeg-6.0 --- srcpkgs/avidemux/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/avidemux/template b/srcpkgs/avidemux/template index 253a0243e225..557285982d2b 100644 --- a/srcpkgs/avidemux/template +++ b/srcpkgs/avidemux/template @@ -1,7 +1,7 @@ # Template file for 'avidemux' pkgname=avidemux version=2.8.0 -revision=2 +revision=3 # Can't be compiled for aarch64, arm* or mips* archs="x86_64* i686*" hostmakedepends="cmake pkg-config qt5-host-tools qt5-devel tar yasm" From 05c99e65835800a528ee3107e6032ef11beade0e Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:45 -0400 Subject: [PATCH 019/113] baresip: revbump for ffmpeg-6.0 --- srcpkgs/baresip/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/baresip/template b/srcpkgs/baresip/template index f1bd1817048b..b21e22334316 100644 --- a/srcpkgs/baresip/template +++ b/srcpkgs/baresip/template @@ -1,7 +1,7 @@ # Template file for 'baresip' pkgname=baresip version=2.10.0 -revision=1 +revision=2 build_style=cmake hostmakedepends="pkg-config glib-devel" makedepends="libgsm-devel libpng-devel openssl-devel libsndfile-devel From 4cdf29f13fc694b13150b060f4d2d0a40fe972a8 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:46 -0400 Subject: [PATCH 020/113] blender: revbump for ffmpeg-6.0 --- srcpkgs/blender/template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srcpkgs/blender/template b/srcpkgs/blender/template index 7a710ac0df49..0f72876d4d70 100644 --- a/srcpkgs/blender/template +++ b/srcpkgs/blender/template @@ -9,8 +9,8 @@ configure_args="-DWITH_INSTALL_PORTABLE=OFF -DWITH_PYTHON_INSTALL=OFF -DWITH_JACK=ON -DWITH_CODEC_FFMPEG=ON -DWITH_CODEC_SNDFILE=ON -DWITH_OPENMP=ON -DWITH_FFTW3=ON -DWITH_MOD_OCEANSIM=ON -DWITH_CYCLES_EMBREE=OFF -DWITH_OPENCOLORIO=ON -DWITH_IMAGE_OPENEXR=ON -DWITH_IMAGE_OPENJPEG=ON -DWITH_OPENSUBDIV=ON - -DWITH_OPENCOLLADA=ON -DWITH_SYSTEM_GLEW=ON -DWITH_OPENVDB=ON -DWITH_ALEMBIC=ON - -DWITH_GHOST_X11=ON -DWITH_GHOST_WAYLAND=ON -DWITH_GHOST_LIBDECOR=ON + -DWITH_OPENCOLLADA=ON -DWITH_OPENVDB=ON -DWITH_ALEMBIC=ON + -DWITH_GHOST_X11=ON -DWITH_GHOST_WAYLAND=ON -DWITH_GHOST_WAYLAND_LIBDECOR=ON -DWITH_BUILDINFO=OFF -DPYTHON_VERSION=${py3_ver} -DPYTHON_LIBPATH=/usr/lib -DPYTHON_LIBRARY=python${py3_ver}${py3_abiver} -DPYTHON_INCLUDE_DIRS=/${py3_inc} -DWITH_SYSTEM_LZO=ON -DWITH_SYSTEM_EIGEN3=ON -DWITH_SYSTEM_FREETYPE=ON" From 940329daae3a14fc45a97c90170a496f9a32d2b7 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:46 -0400 Subject: [PATCH 021/113] cantata: revbump for ffmpeg-6.0 --- srcpkgs/cantata/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/cantata/template b/srcpkgs/cantata/template index 4b417d80d5c2..8a90aaa4c07a 100644 --- a/srcpkgs/cantata/template +++ b/srcpkgs/cantata/template @@ -1,7 +1,7 @@ # Template file for 'cantata' pkgname=cantata version=2.5.0 -revision=1 +revision=2 build_style=cmake hostmakedepends="pkg-config qt5-qmake qt5-host-tools qt5-tools" makedepends="qt5-devel qt5-tools-devel qt5-svg-devel qt5-xmlpatterns-devel From 62a08119df80003aafbca5afc1bf1cbc98a398a8 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:46 -0400 Subject: [PATCH 022/113] ccextractor: revbump for ffmpeg4-4.4.3 --- srcpkgs/ccextractor/template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srcpkgs/ccextractor/template b/srcpkgs/ccextractor/template index 9abcd82852b2..6eccad5885af 100644 --- a/srcpkgs/ccextractor/template +++ b/srcpkgs/ccextractor/template @@ -1,12 +1,12 @@ # Template file for 'ccextractor' pkgname=ccextractor version=0.93 -revision=1 +revision=2 build_wrksrc="linux" build_style=gnu-configure configure_args="--enable-ocr --enable-hardsubx" hostmakedepends="automake pkg-config" -makedepends="leptonica-devel tesseract-ocr-devel ffmpeg-devel" +makedepends="leptonica-devel tesseract-ocr-devel ffmpeg4-devel" short_desc="Extract subtitles from video streams" maintainer="newbluemoon " license="GPL-2.0-or-later" From bb99ad93f5d502850711fcd08e54c4a9e96750a9 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:46 -0400 Subject: [PATCH 023/113] chromaprint: revbump for ffmpeg-6.0 --- srcpkgs/chromaprint/patches/ffmpeg5.patch | 569 ++++++++++++++++++++++ srcpkgs/chromaprint/template | 2 +- 2 files changed, 570 insertions(+), 1 deletion(-) create mode 100644 srcpkgs/chromaprint/patches/ffmpeg5.patch diff --git a/srcpkgs/chromaprint/patches/ffmpeg5.patch b/srcpkgs/chromaprint/patches/ffmpeg5.patch new file mode 100644 index 000000000000..a9fd307a23c8 --- /dev/null +++ b/srcpkgs/chromaprint/patches/ffmpeg5.patch @@ -0,0 +1,569 @@ +From 8ccad6937177b1b92e40ab8f4447ea27bac009a7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lalinsk=C3=BD?= +Date: Fri, 4 Nov 2022 21:47:38 +0100 +Subject: [PATCH] Use FFmpeg 5.x (#120) + +* Use FFmpeg 5.1.2 for CI builds + +* Build on Ubuntu 20.04 + +* Upgrade code to FFmpeg 5.x APIs + +* Only set FFmpeg include dirs if building tools + +* No longer needed + +* Use ubuntu 20.04 +--- + .github/workflows/build.yml | 6 +- + CMakeLists.txt | 16 -- + package/build.sh | 4 +- + src/audio/ffmpeg_audio_processor.h | 2 - + src/audio/ffmpeg_audio_processor_avresample.h | 72 ------- + src/audio/ffmpeg_audio_processor_swresample.h | 18 +- + src/audio/ffmpeg_audio_reader.h | 197 +++++++++--------- + tests/CMakeLists.txt | 6 + + 8 files changed, 122 insertions(+), 199 deletions(-) + delete mode 100644 src/audio/ffmpeg_audio_processor_avresample.h + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index f8d6a32..4da2405 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -84,9 +84,6 @@ find_package(FFmpeg) + if(FFMPEG_LIBRARIES) + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_LIBRARIES ${FFMPEG_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} -lm) +- check_function_exists(av_packet_unref HAVE_AV_PACKET_UNREF) +- check_function_exists(av_frame_alloc HAVE_AV_FRAME_ALLOC) +- check_function_exists(av_frame_free HAVE_AV_FRAME_FREE) + cmake_pop_check_state() + endif() + +@@ -163,14 +160,11 @@ message(STATUS "Using ${FFT_LIB} for FFT calculations") + if(NOT AUDIO_PROCESSOR_LIB) + if(FFMPEG_LIBSWRESAMPLE_FOUND) + set(AUDIO_PROCESSOR_LIB "swresample") +- elseif(FFMPEG_LIBAVRESAMPLE_FOUND) +- set(AUDIO_PROCESSOR_LIB "avresample") + endif() + endif() + + if(AUDIO_PROCESSOR_LIB STREQUAL "swresample") + if(FFMPEG_LIBSWRESAMPLE_FOUND) +- set(USE_AVRESAMPLE OFF) + set(USE_SWRESAMPLE ON) + set(AUDIO_PROCESSOR_LIBRARIES ${FFMPEG_LIBSWRESAMPLE_LIBRARIES}) + set(AUDIO_PROCESSOR_INCLUDE_DIRS ${FFMPEG_LIBSWRESAMPLE_INCLUDE_DIRS}) +@@ -178,16 +172,6 @@ if(AUDIO_PROCESSOR_LIB STREQUAL "swresample") + message(FATAL_ERROR "Selected ${AUDIO_PROCESSOR_LIB} for audio processing, but the library is not found") + endif() + message(STATUS "Using ${AUDIO_PROCESSOR_LIB} for audio conversion") +-elseif(AUDIO_PROCESSOR_LIB STREQUAL "avresample") +- if(FFMPEG_LIBAVRESAMPLE_FOUND) +- set(USE_AVRESAMPLE ON) +- set(USE_SWRESAMPLE OFF) +- set(AUDIO_PROCESSOR_LIBRARIES ${FFMPEG_LIBAVRESAMPLE_LIBRARIES}) +- set(AUDIO_PROCESSOR_INCLUDE_DIRS ${FFMPEG_LIBAVRESAMPLE_INCLUDE_DIRS}) +- else() +- message(FATAL_ERROR "Selected ${AUDIO_PROCESSOR_LIB} for audio processing, but the library is not found") +- endif() +- message(STATUS "Using ${AUDIO_PROCESSOR_LIB} for audio conversion") + else() + message(STATUS "Building without audio conversion support, please install FFmpeg with libswresample") + endif() +diff --git a/package/build.sh b/package/build.sh +index da631ae..b41d36e 100755 +--- a/package/build.sh ++++ b/package/build.sh +@@ -7,8 +7,8 @@ set -eux + + BASE_DIR=$(cd $(dirname $0)/.. && pwd) + +-FFMPEG_VERSION=4.4.1 +-FFMPEG_BUILD_TAG=v4.4.1-1 ++FFMPEG_VERSION=5.1.2 ++FFMPEG_BUILD_TAG=v${FFMPEG_VERSION}-1 + + TMP_BUILD_DIR=$BASE_DIR/$(mktemp -d build.XXXXXXXX) + trap 'rm -rf $TMP_BUILD_DIR' EXIT +diff --git a/src/audio/ffmpeg_audio_processor.h b/src/audio/ffmpeg_audio_processor.h +index 7628fc7..39f4f6d 100644 +--- a/src/audio/ffmpeg_audio_processor.h ++++ b/src/audio/ffmpeg_audio_processor.h +@@ -10,8 +10,6 @@ + + #if defined(USE_SWRESAMPLE) + #include "audio/ffmpeg_audio_processor_swresample.h" +-#elif defined(USE_AVRESAMPLE) +-#include "audio/ffmpeg_audio_processor_avresample.h" + #else + #error "no audio processing library" + #endif +diff --git a/src/audio/ffmpeg_audio_processor_avresample.h b/src/audio/ffmpeg_audio_processor_avresample.h +deleted file mode 100644 +index bd85f92..0000000 +--- a/src/audio/ffmpeg_audio_processor_avresample.h ++++ /dev/null +@@ -1,72 +0,0 @@ +-// Copyright (C) 2016 Lukas Lalinsky +-// Distributed under the MIT license, see the LICENSE file for details. +- +-#ifndef CHROMAPRINT_AUDIO_FFMPEG_AUDIO_PROCESSOR_AVRESAMPLE_H_ +-#define CHROMAPRINT_AUDIO_FFMPEG_AUDIO_PROCESSOR_AVRESAMPLE_H_ +- +-extern "C" { +-#include +-} +- +-namespace chromaprint { +- +-class FFmpegAudioProcessor { +-public: +- FFmpegAudioProcessor() { +- m_resample_ctx = avresample_alloc_context(); +- } +- +- ~FFmpegAudioProcessor() { +- avresample_free(&m_resample_ctx); +- } +- +- void SetCompatibleMode() { +- av_opt_set_int(m_resample_ctx, "filter_size", 16, 0); +- av_opt_set_int(m_resample_ctx, "phase_shift", 8, 0); +- av_opt_set_int(m_resample_ctx, "linear_interp", 1, 0); +- av_opt_set_double(m_resample_ctx, "cutoff", 0.8, 0); +- } +- +- void SetInputChannelLayout(int64_t channel_layout) { +- av_opt_set_int(m_resample_ctx, "in_channel_layout", channel_layout, 0); +- } +- +- void SetInputSampleFormat(AVSampleFormat sample_format) { +- av_opt_set_int(m_resample_ctx, "in_sample_fmt", sample_format, 0); +- } +- +- void SetInputSampleRate(int sample_rate) { +- av_opt_set_int(m_resample_ctx, "in_sample_rate", sample_rate, 0); +- } +- +- void SetOutputChannelLayout(int64_t channel_layout) { +- av_opt_set_int(m_resample_ctx, "out_channel_layout", channel_layout, 0); +- } +- +- void SetOutputSampleFormat(AVSampleFormat sample_format) { +- av_opt_set_int(m_resample_ctx, "out_sample_fmt", sample_format, 0); +- } +- +- void SetOutputSampleRate(int sample_rate) { +- av_opt_set_int(m_resample_ctx, "out_sample_fmt", sample_rate, 0); +- } +- +- int Init() { +- return avresample_open(m_resample_ctx); +- } +- +- int Convert(uint8_t **out, int out_count, const uint8_t **in, int in_count) { +- return avresample_convert(m_resample_ctx, out, 0, out_count, (uint8_t **) in, 0, in_count); +- } +- +- int Flush(uint8_t **out, int out_count) { +- return avresample_read(m_resample_ctx, out, out_count); +- } +- +-private: +- AVAudioResampleContext *m_resample_ctx = nullptr; +-}; +- +-}; // namespace chromaprint +- +-#endif +diff --git a/src/audio/ffmpeg_audio_processor_swresample.h b/src/audio/ffmpeg_audio_processor_swresample.h +index b86266b..b1d4bea 100644 +--- a/src/audio/ffmpeg_audio_processor_swresample.h ++++ b/src/audio/ffmpeg_audio_processor_swresample.h +@@ -28,30 +28,28 @@ public: + av_opt_set_double(m_swr_ctx, "cutoff", 0.8, 0); + } + +- void SetInputChannelLayout(int64_t channel_layout) { +- av_opt_set_int(m_swr_ctx, "icl", channel_layout, 0); +- av_opt_set_int(m_swr_ctx, "ich", av_get_channel_layout_nb_channels(channel_layout), 0); ++ void SetInputChannelLayout(AVChannelLayout *channel_layout) { ++ av_opt_set_int(m_swr_ctx, "in_channel_layout", channel_layout->u.mask, 0); + } + + void SetInputSampleFormat(AVSampleFormat sample_format) { +- av_opt_set_int(m_swr_ctx, "isf", sample_format, 0); ++ av_opt_set_sample_fmt(m_swr_ctx, "in_sample_fmt", sample_format, 0); + } + + void SetInputSampleRate(int sample_rate) { +- av_opt_set_int(m_swr_ctx, "isr", sample_rate, 0); ++ av_opt_set_int(m_swr_ctx, "in_sample_rate", sample_rate, 0); + } + +- void SetOutputChannelLayout(int64_t channel_layout) { +- av_opt_set_int(m_swr_ctx, "ocl", channel_layout, 0); +- av_opt_set_int(m_swr_ctx, "och", av_get_channel_layout_nb_channels(channel_layout), 0); ++ void SetOutputChannelLayout(AVChannelLayout *channel_layout) { ++ av_opt_set_int(m_swr_ctx, "out_channel_layout", channel_layout->u.mask, 0); + } + + void SetOutputSampleFormat(AVSampleFormat sample_format) { +- av_opt_set_int(m_swr_ctx, "osf", sample_format, 0); ++ av_opt_set_sample_fmt(m_swr_ctx, "out_sample_fmt", sample_format, 0); + } + + void SetOutputSampleRate(int sample_rate) { +- av_opt_set_int(m_swr_ctx, "osr", sample_rate, 0); ++ av_opt_set_int(m_swr_ctx, "out_sample_rate", sample_rate, 0); + } + + int Init() { +diff --git a/src/audio/ffmpeg_audio_reader.h b/src/audio/ffmpeg_audio_reader.h +index 5550164..1c6b346 100644 +--- a/src/audio/ffmpeg_audio_reader.h ++++ b/src/audio/ffmpeg_audio_reader.h +@@ -62,7 +62,7 @@ public: + bool Read(const int16_t **data, size_t *size); + + bool IsOpen() const { return m_opened; } +- bool IsFinished() const { return m_finished && !m_got_frame; } ++ bool IsFinished() const { return !m_has_more_packets && !m_has_more_frames; } + + std::string GetError() const { return m_error; } + int GetErrorCode() const { return m_error_code; } +@@ -74,20 +74,19 @@ private: + uint8_t *m_convert_buffer[1] = { nullptr }; + int m_convert_buffer_nb_samples = 0; + +- AVInputFormat *m_input_fmt = nullptr; ++ const AVInputFormat *m_input_fmt = nullptr; + AVDictionary *m_input_opts = nullptr; + + AVFormatContext *m_format_ctx = nullptr; + AVCodecContext *m_codec_ctx = nullptr; +- AVFrame *m_frame = nullptr; + int m_stream_index = -1; + std::string m_error; + int m_error_code = 0; +- bool m_finished = false; + bool m_opened = false; +- int m_got_frame = 0; +- AVPacket m_packet; +- AVPacket m_packet0; ++ bool m_has_more_packets = true; ++ bool m_has_more_frames = true; ++ AVPacket *m_packet = nullptr; ++ AVFrame *m_frame = nullptr; + + int m_output_sample_rate = 0; + int m_output_channels = 0; +@@ -98,19 +97,12 @@ private: + + inline FFmpegAudioReader::FFmpegAudioReader() { + av_log_set_level(AV_LOG_QUIET); +- +- av_init_packet(&m_packet); +- m_packet.data = nullptr; +- m_packet.size = 0; +- +- m_packet0 = m_packet; + } + + inline FFmpegAudioReader::~FFmpegAudioReader() { + Close(); + av_dict_free(&m_input_opts); + av_freep(&m_convert_buffer[0]); +- av_packet_unref(&m_packet0); + } + + inline bool FFmpegAudioReader::SetInputFormat(const char *name) { +@@ -135,11 +127,10 @@ inline bool FFmpegAudioReader::Open(const std::string &file_name) { + + Close(); + +- av_init_packet(&m_packet); +- m_packet.data = nullptr; +- m_packet.size = 0; +- +- m_packet0 = m_packet; ++ m_packet = av_packet_alloc(); ++ if (!m_packet) { ++ return false; ++ } + + ret = avformat_open_input(&m_format_ctx, file_name.c_str(), m_input_fmt, &m_input_opts); + if (ret < 0) { +@@ -153,26 +144,31 @@ inline bool FFmpegAudioReader::Open(const std::string &file_name) { + return false; + } + +- AVCodec *codec; ++ const AVCodec *codec; + ret = av_find_best_stream(m_format_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0); + if (ret < 0) { + SetError("Could not find any audio stream in the file", ret); + return false; + } + m_stream_index = ret; ++ auto stream = m_format_ctx->streams[m_stream_index]; + +- m_codec_ctx = m_format_ctx->streams[m_stream_index]->codec; ++ m_codec_ctx = avcodec_alloc_context3(codec); + m_codec_ctx->request_sample_fmt = AV_SAMPLE_FMT_S16; + ++ ret = avcodec_parameters_to_context(m_codec_ctx, stream->codecpar); ++ if (ret < 0) { ++ SetError("Could not copy the stream parameters", ret); ++ return false; ++ } ++ + ret = avcodec_open2(m_codec_ctx, codec, nullptr); + if (ret < 0) { + SetError("Could not open the codec", ret); + return false; + } + +- if (!m_codec_ctx->channel_layout) { +- m_codec_ctx->channel_layout = av_get_default_channel_layout(m_codec_ctx->channels); +- } ++ av_dump_format(m_format_ctx, 0, "foo", 0); + + m_frame = av_frame_alloc(); + if (!m_frame) { +@@ -183,19 +179,23 @@ inline bool FFmpegAudioReader::Open(const std::string &file_name) { + m_output_sample_rate = m_codec_ctx->sample_rate; + } + +- if (!m_output_channels) { +- m_output_channels = m_codec_ctx->channels; ++ AVChannelLayout output_channel_layout; ++ if (m_output_channels) { ++ av_channel_layout_default(&output_channel_layout, m_output_channels); ++ } else { ++ m_output_channels = m_codec_ctx->ch_layout.nb_channels; ++ av_channel_layout_default(&output_channel_layout, m_output_channels); + } + +- if (m_codec_ctx->sample_fmt != AV_SAMPLE_FMT_S16 || m_codec_ctx->channels != m_output_channels || m_codec_ctx->sample_rate != m_output_sample_rate) { ++ if (m_codec_ctx->sample_fmt != AV_SAMPLE_FMT_S16 || m_codec_ctx->ch_layout.nb_channels != m_output_channels || m_codec_ctx->sample_rate != m_output_sample_rate) { + m_converter.reset(new FFmpegAudioProcessor()); + m_converter->SetCompatibleMode(); + m_converter->SetInputSampleFormat(m_codec_ctx->sample_fmt); + m_converter->SetInputSampleRate(m_codec_ctx->sample_rate); +- m_converter->SetInputChannelLayout(m_codec_ctx->channel_layout); ++ m_converter->SetInputChannelLayout(&(m_codec_ctx->ch_layout)); + m_converter->SetOutputSampleFormat(AV_SAMPLE_FMT_S16); + m_converter->SetOutputSampleRate(m_output_sample_rate); +- m_converter->SetOutputChannelLayout(av_get_default_channel_layout(m_output_channels)); ++ m_converter->SetOutputChannelLayout(&output_channel_layout); + auto ret = m_converter->Init(); + if (ret != 0) { + SetError("Could not create an audio converter instance", ret); +@@ -203,10 +203,11 @@ inline bool FFmpegAudioReader::Open(const std::string &file_name) { + } + } + ++ av_channel_layout_uninit(&output_channel_layout); ++ + m_opened = true; +- m_finished = false; +- m_got_frame = 0; +- m_nb_packets = 0; ++ m_has_more_packets = true; ++ m_has_more_frames = true; + m_decode_error = 0; + + return true; +@@ -214,6 +215,7 @@ inline bool FFmpegAudioReader::Open(const std::string &file_name) { + + inline void FFmpegAudioReader::Close() { + av_frame_free(&m_frame); ++ av_packet_free(&m_packet); + + m_stream_index = -1; + +@@ -252,91 +254,98 @@ inline bool FFmpegAudioReader::Read(const int16_t **data, size_t *size) { + return false; + } + ++ *data = nullptr; ++ *size = 0; ++ + int ret; ++ bool needs_packet = false; + while (true) { +- while (m_packet.size <= 0) { +- av_packet_unref(&m_packet0); +- av_init_packet(&m_packet); +- m_packet.data = nullptr; +- m_packet.size = 0; +- ret = av_read_frame(m_format_ctx, &m_packet); ++ while (needs_packet && m_packet->size == 0) { ++ ret = av_read_frame(m_format_ctx, m_packet); + if (ret < 0) { + if (ret == AVERROR_EOF) { +- m_finished = true; ++ needs_packet = false; ++ m_has_more_packets = false; + break; +- } else { ++ } ++ SetError("Error reading from the audio source", ret); ++ return false; ++ } ++ if (m_packet->stream_index == m_stream_index) { ++ needs_packet = false; ++ } else { ++ av_packet_unref(m_packet); ++ } ++ } ++ ++ if (m_packet->size != 0) { ++ ret = avcodec_send_packet(m_codec_ctx, m_packet); ++ if (ret < 0) { ++ if (ret != AVERROR(EAGAIN)) { + SetError("Error reading from the audio source", ret); + return false; + } +- } +- m_packet0 = m_packet; +- if (m_packet.stream_index != m_stream_index) { +- m_packet.data = nullptr; +- m_packet.size = 0; + } else { +- m_nb_packets++; ++ av_packet_unref(m_packet); + } + } + +- ret = avcodec_decode_audio4(m_codec_ctx, m_frame, &m_got_frame, &m_packet); ++ ret = avcodec_receive_frame(m_codec_ctx, m_frame); + if (ret < 0) { +- if (m_decode_error) { +- SetError("Error decoding audio frame", m_decode_error); +- return false; ++ if (ret == AVERROR_EOF) { ++ m_has_more_frames = false; ++ } else if (ret == AVERROR(EAGAIN)) { ++ if (m_has_more_packets) { ++ needs_packet = true; ++ continue; ++ } else { ++ m_has_more_frames = false; ++ } + } +- m_decode_error = ret; +- m_packet.data = nullptr; +- m_packet.size = 0; +- continue; ++ SetError("Error decoding the audio source", ret); ++ return false; + } + +- break; +- } +- +- m_decode_error = 0; +- +- const int decoded = std::min(ret, m_packet.size); +- m_packet.data += decoded; +- m_packet.size -= decoded; +- +- if (m_got_frame) { +- if (m_converter) { +- if (m_frame->nb_samples > m_convert_buffer_nb_samples) { +- int linsize; +- av_freep(&m_convert_buffer[0]); +- m_convert_buffer_nb_samples = std::max(1024 * 8, m_frame->nb_samples); +- ret = av_samples_alloc(m_convert_buffer, &linsize, m_codec_ctx->channels, m_convert_buffer_nb_samples, AV_SAMPLE_FMT_S16, 1); +- if (ret < 0) { +- SetError("Couldn't allocate audio converter buffer", ret); ++ if (m_frame->nb_samples > 0) { ++ if (m_converter) { ++ if (m_frame->nb_samples > m_convert_buffer_nb_samples) { ++ int linsize; ++ av_freep(&m_convert_buffer[0]); ++ m_convert_buffer_nb_samples = std::max(1024 * 8, m_frame->nb_samples); ++ ret = av_samples_alloc(m_convert_buffer, &linsize, m_codec_ctx->ch_layout.nb_channels, m_convert_buffer_nb_samples, AV_SAMPLE_FMT_S16, 1); ++ if (ret < 0) { ++ SetError("Couldn't allocate audio converter buffer", ret); ++ return false; ++ } ++ } ++ auto nb_samples = m_converter->Convert(m_convert_buffer, m_convert_buffer_nb_samples, (const uint8_t **) m_frame->data, m_frame->nb_samples); ++ if (nb_samples < 0) { ++ SetError("Couldn't convert audio", ret); + return false; + } +- } +- auto nb_samples = m_converter->Convert(m_convert_buffer, m_convert_buffer_nb_samples, (const uint8_t **) m_frame->data, m_frame->nb_samples); +- if (nb_samples < 0) { +- SetError("Couldn't convert audio", ret); +- return false; +- } +- *data = (const int16_t *) m_convert_buffer[0]; +- *size = nb_samples; +- } else { +- *data = (const int16_t *) m_frame->data[0]; +- *size = m_frame->nb_samples; +- } +- } else { +- if (m_finished && m_converter) { +- auto nb_samples = m_converter->Flush(m_convert_buffer, m_convert_buffer_nb_samples); +- if (nb_samples < 0) { +- SetError("Couldn't convert audio", ret); +- return false; +- } else if (nb_samples > 0) { +- m_got_frame = 1; + *data = (const int16_t *) m_convert_buffer[0]; + *size = nb_samples; ++ } else { ++ *data = (const int16_t *) m_frame->data[0]; ++ *size = m_frame->nb_samples; ++ } ++ } else { ++ if (m_converter) { ++ if (IsFinished()) { ++ auto nb_samples = m_converter->Flush(m_convert_buffer, m_convert_buffer_nb_samples); ++ if (nb_samples < 0) { ++ SetError("Couldn't convert audio", ret); ++ return false; ++ } else if (nb_samples > 0) { ++ *data = (const int16_t *) m_convert_buffer[0]; ++ *size = nb_samples; ++ } ++ } + } + } +- } + +- return true; ++ return true; ++ } + } + + inline void FFmpegAudioReader::SetError(const char *message, int errnum) { +diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt +index a2b517b..123e643 100644 +--- a/tests/CMakeLists.txt ++++ b/tests/CMakeLists.txt +@@ -38,6 +38,12 @@ set(SRCS + + if(BUILD_TOOLS) + set(SRCS ${SRCS} ../src/audio/ffmpeg_audio_reader_test.cpp) ++ include_directories( ++ ${FFMPEG_LIBAVFORMAT_INCLUDE_DIRS} ++ ${FFMPEG_LIBAVCODEC_INCLUDE_DIRS} ++ ${FFMPEG_LIBAVUTIL_INCLUDE_DIRS} ++ ${AUDIO_PROCESSOR_INCLUDE_DIRS} ++ ) + link_libraries(fpcalc_libs) + endif() + +-- +2.38.1 + + diff --git a/srcpkgs/chromaprint/template b/srcpkgs/chromaprint/template index 7ef7838949f3..1f7bbc70a22c 100644 --- a/srcpkgs/chromaprint/template +++ b/srcpkgs/chromaprint/template @@ -1,7 +1,7 @@ # Template file for 'chromaprint' pkgname=chromaprint version=1.5.1 -revision=1 +revision=2 build_style=cmake configure_args="-DBUILD_TOOLS=ON" make_check_target="check" From 1c6da6d1d2cf6bafddd5d947c6c9d44e5ea9e728 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:46 -0400 Subject: [PATCH 024/113] chromium: revbump for ffmpeg-6.0 --- .../patches/chromium-93-ffmpeg-4.4.patch | 36 -------------- srcpkgs/chromium/patches/ffmpeg5.patch | 47 +++++++++++++++++++ srcpkgs/chromium/template | 2 +- 3 files changed, 48 insertions(+), 37 deletions(-) delete mode 100644 srcpkgs/chromium/patches/chromium-93-ffmpeg-4.4.patch create mode 100644 srcpkgs/chromium/patches/ffmpeg5.patch diff --git a/srcpkgs/chromium/patches/chromium-93-ffmpeg-4.4.patch b/srcpkgs/chromium/patches/chromium-93-ffmpeg-4.4.patch deleted file mode 100644 index f0ec736f98bc..000000000000 --- a/srcpkgs/chromium/patches/chromium-93-ffmpeg-4.4.patch +++ /dev/null @@ -1,36 +0,0 @@ -diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc -index ac4713b07268..492a9a37d096 100644 ---- a/media/filters/ffmpeg_demuxer.cc -+++ b/media/filters/ffmpeg_demuxer.cc -@@ -427,11 +427,11 @@ void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { - scoped_refptr buffer; - - if (type() == DemuxerStream::TEXT) { -- size_t id_size = 0; -+ int id_size = 0; - uint8_t* id_data = av_packet_get_side_data( - packet.get(), AV_PKT_DATA_WEBVTT_IDENTIFIER, &id_size); - -- size_t settings_size = 0; -+ int settings_size = 0; - uint8_t* settings_data = av_packet_get_side_data( - packet.get(), AV_PKT_DATA_WEBVTT_SETTINGS, &settings_size); - -@@ -443,7 +443,7 @@ void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { - buffer = DecoderBuffer::CopyFrom(packet->data, packet->size, - side_data.data(), side_data.size()); - } else { -- size_t side_data_size = 0; -+ int side_data_size = 0; - uint8_t* side_data = av_packet_get_side_data( - packet.get(), AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, &side_data_size); - -@@ -504,7 +504,7 @@ void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { - packet->size - data_offset); - } - -- size_t skip_samples_size = 0; -+ int skip_samples_size = 0; - const uint32_t* skip_samples_ptr = - reinterpret_cast(av_packet_get_side_data( - packet.get(), AV_PKT_DATA_SKIP_SAMPLES, &skip_samples_size)); diff --git a/srcpkgs/chromium/patches/ffmpeg5.patch b/srcpkgs/chromium/patches/ffmpeg5.patch new file mode 100644 index 000000000000..24e2da38e34c --- /dev/null +++ b/srcpkgs/chromium/patches/ffmpeg5.patch @@ -0,0 +1,47 @@ +--- a/media/filters/ffmpeg_demuxer.cc 2023-01-23 17:33:57.366213805 +0200 ++++ b/media/filters/ffmpeg_demuxer.cc 2023-01-23 17:43:09.283436983 +0200 +@@ -92,24 +92,12 @@ + + static base::TimeDelta ExtractStartTime(AVStream* stream) { + // The default start time is zero. +- base::TimeDelta start_time; ++ base::TimeDelta start_time = kNoTimestamp; + + // First try to use the |start_time| value as is. +- if (stream->start_time != kNoFFmpegTimestamp) ++ if (stream->start_time != kNoFFmpegTimestamp) // AV_NOPTS_VALUE + start_time = ConvertFromTimeBase(stream->time_base, stream->start_time); + +- // Next try to use the first DTS value, for codecs where we know PTS == DTS +- // (excludes all H26x codecs). The start time must be returned in PTS. +- if (av_stream_get_first_dts(stream) != kNoFFmpegTimestamp && +- stream->codecpar->codec_id != AV_CODEC_ID_HEVC && +- stream->codecpar->codec_id != AV_CODEC_ID_H264 && +- stream->codecpar->codec_id != AV_CODEC_ID_MPEG4) { +- const base::TimeDelta first_pts = +- ConvertFromTimeBase(stream->time_base, av_stream_get_first_dts(stream)); +- if (first_pts < start_time) +- start_time = first_pts; +- } +- + return start_time; + } + +@@ -1597,7 +1585,7 @@ + for (const auto& stream : streams_) { + if (!stream || stream->IsEnabled() != enabled) + continue; +- if (av_stream_get_first_dts(stream->av_stream()) == kInvalidPTSMarker) ++ if (stream->av_stream()->start_time == AV_NOPTS_VALUE) + continue; + if (!lowest_start_time_stream || + stream->start_time() < lowest_start_time_stream->start_time()) { +@@ -1618,7 +1606,7 @@ + if (stream->type() != DemuxerStream::VIDEO) + continue; + +- if (av_stream_get_first_dts(stream->av_stream()) == kInvalidPTSMarker) ++ if (stream->av_stream()->start_time == AV_NOPTS_VALUE) + continue; + + if (!stream->IsEnabled()) diff --git a/srcpkgs/chromium/template b/srcpkgs/chromium/template index b4a39dfd3815..c29453cd1f50 100644 --- a/srcpkgs/chromium/template +++ b/srcpkgs/chromium/template @@ -2,7 +2,7 @@ pkgname=chromium # See https://chromiumdash.appspot.com/releases?platform=Linux for the latest version version=114.0.5735.106 -revision=1 +revision=2 archs="i686* x86_64* aarch64* armv7l*" hostmakedepends=" $(vopt_if clang "clang lld llvm15") From a2d6b14b4272b17888d709d2ba8eabcf91529cb1 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:46 -0400 Subject: [PATCH 025/113] cmus: revbump for ffmpeg-6.0 --- srcpkgs/cmus/patches/ffmpeg6.patch | 12 ++++++++++++ srcpkgs/cmus/template | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 srcpkgs/cmus/patches/ffmpeg6.patch diff --git a/srcpkgs/cmus/patches/ffmpeg6.patch b/srcpkgs/cmus/patches/ffmpeg6.patch new file mode 100644 index 000000000000..ffa95ab81110 --- /dev/null +++ b/srcpkgs/cmus/patches/ffmpeg6.patch @@ -0,0 +1,12 @@ +--- a/ip/ffmpeg.c ++++ b/ip/ffmpeg.c +@@ -202,9 +202,6 @@ static int ffmpeg_open(struct input_plugin_data *ip_data) + break; + } + +- if (codec->capabilities & AV_CODEC_CAP_TRUNCATED) +- cc->flags |= AV_CODEC_FLAG_TRUNCATED; +- + if (avcodec_open2(cc, codec, NULL) < 0) { + d_print("could not open codec: %d, %s\n", cc->codec_id, avcodec_get_name(cc->codec_id)); + err = -IP_ERROR_UNSUPPORTED_FILE_TYPE; diff --git a/srcpkgs/cmus/template b/srcpkgs/cmus/template index 0fcb424ce336..05b77d0fecae 100644 --- a/srcpkgs/cmus/template +++ b/srcpkgs/cmus/template @@ -1,7 +1,7 @@ # Template file for 'cmus' pkgname=cmus version=2.10.0 -revision=1 +revision=2 build_style=configure configure_args="prefix=/usr LD=$CC" hostmakedepends="pkg-config" From b55280f16d6a828267eeb799c0e6ccc435da8490 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:46 -0400 Subject: [PATCH 026/113] cyanrip: revbump for ffmpeg-6.0 --- srcpkgs/cyanrip/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/cyanrip/template b/srcpkgs/cyanrip/template index 9796e3461601..5db30e020d17 100644 --- a/srcpkgs/cyanrip/template +++ b/srcpkgs/cyanrip/template @@ -1,7 +1,7 @@ # Template file for 'cyanrip' pkgname=cyanrip version=0.9.0 -revision=1 +revision=2 build_style=meson hostmakedepends="pkg-config" makedepends="ffmpeg-devel libcdio-devel libcdio-paranoia-devel libcurl-devel libmusicbrainz5-devel" From 800906a10adf795f982b438446e34b3f3224026b Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:46 -0400 Subject: [PATCH 027/113] deadbeef: revbump for ffmpeg4-4.4.3 --- srcpkgs/deadbeef/template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srcpkgs/deadbeef/template b/srcpkgs/deadbeef/template index b664bb1b9bd9..165b3c7b9cad 100644 --- a/srcpkgs/deadbeef/template +++ b/srcpkgs/deadbeef/template @@ -1,14 +1,14 @@ # Template file for 'deadbeef' pkgname=deadbeef version=1.8.8 -revision=1 +revision=2 create_wrksrc=yes build_style=gnu-configure configure_args="--disable-oss --disable-lfm --disable-notify --disable-gtk2" hostmakedepends="automake libtool gettext gettext-devel intltool pkg-config yasm clang glib-devel" makedepends=" - alsa-lib-devel dbus-devel faad2-devel ffmpeg-devel gtk+3-devel imlib2-devel + alsa-lib-devel dbus-devel faad2-devel ffmpeg4-devel gtk+3-devel imlib2-devel jansson-devel libcddb-devel libcdio-devel libcurl-devel libflac-devel libmad-devel libpng-devel libsamplerate-devel libsndfile-devel libvorbis-devel libzip-devel mpg123-devel opusfile-devel pulseaudio-devel wavpack-devel" From 8dd109c892c872c5e84531070a9e769e4701d707 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:46 -0400 Subject: [PATCH 028/113] dolphin-emu: revbump for ffmpeg-6.0 --- srcpkgs/dolphin-emu/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/dolphin-emu/template b/srcpkgs/dolphin-emu/template index 7ea197ceb2a8..7aeb0a5b645e 100644 --- a/srcpkgs/dolphin-emu/template +++ b/srcpkgs/dolphin-emu/template @@ -1,7 +1,7 @@ # Template file for 'dolphin-emu' pkgname=dolphin-emu version=5.0.16101 -revision=1 +revision=2 _dolphin_commit=8ecfa537a242de74d2e372e30d9d79b14584b2fb _mgba_commit=40d4c430fc36caeb7ea32fd39624947ed487d2f2 #Version/hash pair can be found at https://dolphin-emu.org/download/ From dd30734a002ffd50973935315d955b5e39f7a58b Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:46 -0400 Subject: [PATCH 029/113] droidcam-obs-plugin: revbump for ffmpeg-6.0 --- srcpkgs/droidcam-obs-plugin/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/droidcam-obs-plugin/template b/srcpkgs/droidcam-obs-plugin/template index fc9c9bf6b9d5..fb0480754df4 100644 --- a/srcpkgs/droidcam-obs-plugin/template +++ b/srcpkgs/droidcam-obs-plugin/template @@ -1,7 +1,7 @@ # Template file for 'droidcam-obs-plugin' pkgname=droidcam-obs-plugin version=2.0.1 -revision=1 +revision=2 build_style=gnu-makefile make_use_env=yes make_build_args="ALLOW_STATIC=no" From 66a4cfc1088c4ad81fd0027ea0de3189d78bf230 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:46 -0400 Subject: [PATCH 030/113] droidcam: revbump for ffmpeg-6.0 --- srcpkgs/droidcam/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/droidcam/template b/srcpkgs/droidcam/template index 1c3f1b8b1fc6..32a9220b79a4 100644 --- a/srcpkgs/droidcam/template +++ b/srcpkgs/droidcam/template @@ -1,7 +1,7 @@ # Template file for 'droidcam' pkgname=droidcam version=1.8.2 -revision=2 +revision=3 build_style=gnu-makefile make_build_args="USBMUXD=-lusbmuxd-2.0 JPEG=-lturbojpeg" hostmakedepends="pkg-config" From 0ca5ac90f8c2ab9c675aa9d4938db2f3b230d6bb Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:47 -0400 Subject: [PATCH 031/113] ffmpegthumbnailer: revbump for ffmpeg-6.0 --- .../ffmpegthumbnailer/patches/ffmpeg6.patch | 202 ++++++++++++++++++ srcpkgs/ffmpegthumbnailer/template | 6 +- 2 files changed, 205 insertions(+), 3 deletions(-) create mode 100644 srcpkgs/ffmpegthumbnailer/patches/ffmpeg6.patch diff --git a/srcpkgs/ffmpegthumbnailer/patches/ffmpeg6.patch b/srcpkgs/ffmpegthumbnailer/patches/ffmpeg6.patch new file mode 100644 index 000000000000..363ff35a2841 --- /dev/null +++ b/srcpkgs/ffmpegthumbnailer/patches/ffmpeg6.patch @@ -0,0 +1,202 @@ +--- a/libffmpegthumbnailer/moviedecoder.cpp 2017-11-21 14:06:57.000000000 -0500 ++++ b/libffmpegthumbnailer/moviedecoder.cpp 2023-05-05 13:14:47.946560668 -0400 +@@ -41,11 +41,6 @@ + namespace ffmpegthumbnailer + { + +-struct SilenceLogLevel +-{ +- SilenceLogLevel() { av_log_set_level(AV_LOG_QUIET); } +-}; +- + MovieDecoder::MovieDecoder(AVFormatContext* pavContext) + : m_VideoStream(-1) + , m_pFormatContext(pavContext) +@@ -70,8 +65,6 @@ + + void MovieDecoder::initialize(const string& filename, bool preferEmbeddedMetadata) + { +- av_register_all(); +- avcodec_register_all(); + avformat_network_init(); + + string inputFile = filename == "-" ? "pipe:" : filename; +@@ -97,8 +90,7 @@ + { + if (m_pVideoCodecContext) + { +- avcodec_close(m_pVideoCodecContext); +- m_pVideoCodecContext = nullptr; ++ avcodec_free_context(&m_pVideoCodecContext); + } + + if ((!m_FormatContextWasGiven) && m_pFormatContext) +@@ -152,10 +144,10 @@ + for (unsigned int i = 0; i < m_pFormatContext->nb_streams; ++i) + { + AVStream *stream = m_pFormatContext->streams[i]; +- auto ctx = m_pFormatContext->streams[i]->codec; +- if (ctx->codec_type == AVMEDIA_TYPE_VIDEO) ++ auto par = m_pFormatContext->streams[i]->codecpar; ++ if (par->codec_type == AVMEDIA_TYPE_VIDEO) + { +- if (!preferEmbeddedMetadata || !isStillImageCodec(ctx->codec_id)) ++ if (!preferEmbeddedMetadata || !isStillImageCodec(par->codec_id)) + { + videoStreams.push_back(i); + continue; +@@ -203,8 +195,7 @@ + } + + m_pVideoStream = m_pFormatContext->streams[m_VideoStream]; +- m_pVideoCodecContext = m_pVideoStream->codec; +- m_pVideoCodec = avcodec_find_decoder(m_pVideoCodecContext->codec_id); ++ m_pVideoCodec = avcodec_find_decoder(m_pVideoStream->codecpar->codec_id); + + if (m_pVideoCodec == nullptr) + { +@@ -214,6 +205,20 @@ + throw logic_error("Video Codec not found"); + } + ++ m_pVideoCodecContext = avcodec_alloc_context3(m_pVideoCodec); ++ ++ if (m_pVideoCodecContext == nullptr) ++ { ++ destroy(); ++ throw logic_error("Could not allocate video codec context"); ++ } ++ ++ if (avcodec_parameters_to_context(m_pVideoCodecContext, m_pVideoStream->codecpar) < 0) ++ { ++ destroy(); ++ throw logic_error("Could not configure video codec context"); ++ } ++ + m_pVideoCodecContext->workaround_bugs = 1; + + if (avcodec_open2(m_pVideoCodecContext, m_pVideoCodec, nullptr) < 0) +@@ -386,13 +391,6 @@ + + void MovieDecoder::initializeFilterGraph(const AVRational& timeBase, const std::string& size, bool maintainAspectRatio) + { +- static const AVPixelFormat pixelFormats[] = { AV_PIX_FMT_RGB24, AV_PIX_FMT_NONE }; +- +- auto del = [] (AVBufferSinkParams* p) { av_freep(p); }; +- std::unique_ptr buffersinkParams(av_buffersink_params_alloc(), del); +- +- avfilter_register_all(); +- + m_pFilterGraph = avfilter_graph_alloc(); + assert(m_pFilterGraph); + +@@ -404,10 +402,8 @@ + + checkRc(avfilter_graph_create_filter(&m_pFilterSource, avfilter_get_by_name("buffer"), "thumb_buffer", ss.str().c_str(), nullptr, m_pFilterGraph), + "Failed to create filter source"); +- buffersinkParams->pixel_fmts = pixelFormats; +- checkRc(avfilter_graph_create_filter(&m_pFilterSink, avfilter_get_by_name("buffersink"), "thumb_buffersink", nullptr, buffersinkParams.get(), m_pFilterGraph), ++ checkRc(avfilter_graph_create_filter(&m_pFilterSink, avfilter_get_by_name("buffersink"), "thumb_buffersink", nullptr, nullptr, m_pFilterGraph), + "Failed to create filter sink"); +- buffersinkParams.release(); + + AVFilterContext* yadifFilter = nullptr; + if (m_pFrame->interlaced_frame != 0) +@@ -500,15 +496,15 @@ + } + + checkRc(av_seek_frame(m_pFormatContext, -1, timestamp, 0), "Seeking in video failed"); +- avcodec_flush_buffers(m_pFormatContext->streams[m_VideoStream]->codec); ++ avcodec_flush_buffers(m_pVideoCodecContext); + + int keyFrameAttempts = 0; +- bool gotFrame = 0; ++ bool gotFrame; + + do + { + int count = 0; +- gotFrame = 0; ++ gotFrame = false; + + while (!gotFrame && count < 20) + { +@@ -552,17 +548,33 @@ + return false; + } + +- av_frame_unref(m_pFrame); +- +- int frameFinished; ++ int rc = avcodec_send_packet(m_pVideoCodecContext, m_pPacket); ++ if(rc == AVERROR(EAGAIN)) ++ { ++ rc = 0; ++ } + +- int bytesDecoded = avcodec_decode_video2(m_pVideoCodecContext, m_pFrame, &frameFinished, m_pPacket); +- if (bytesDecoded < 0) ++ if(rc == AVERROR_EOF) ++ { ++ return false; ++ } ++ else if(rc < 0) + { +- throw logic_error("Failed to decode video frame: bytesDecoded < 0"); ++ throw logic_error("Failed to decode video frame: avcodec_send_packet() < 0"); + } + +- return frameFinished > 0; ++ rc = avcodec_receive_frame(m_pVideoCodecContext, m_pFrame); ++ switch(rc) ++ { ++ case 0: ++ return true; ++ ++ case AVERROR(EAGAIN): ++ return false; ++ ++ default: ++ throw logic_error("Failed to decode video frame: avcodec_receive_frame() < 0"); ++ } + } + + bool MovieDecoder::getVideoPacket() +@@ -570,8 +582,6 @@ + bool framesAvailable = true; + bool frameDecoded = false; + +- int attempts = 0; +- + if (m_pPacket) + { + av_packet_unref(m_pPacket); +@@ -580,6 +590,7 @@ + + m_pPacket = new AVPacket(); + ++ + while (framesAvailable && !frameDecoded) + { + framesAvailable = av_read_frame(m_pFormatContext, m_pPacket) >= 0; +@@ -644,7 +655,7 @@ + + int32_t MovieDecoder::getStreamRotation() + { +- int32_t* matrix = reinterpret_cast(av_stream_get_side_data(m_pVideoStream, AV_PKT_DATA_DISPLAYMATRIX, nullptr)); ++ auto matrix = reinterpret_cast(av_stream_get_side_data(m_pVideoStream, AV_PKT_DATA_DISPLAYMATRIX, nullptr)); + if (matrix) + { + auto angle = lround(av_display_rotation_get(matrix)); + +--- a/libffmpegthumbnailer/moviedecoder.h 2017-11-12 04:23:38.000000000 -0500 ++++ b/libffmpegthumbnailer/moviedecoder.h 2023-05-05 13:26:07.095529911 -0400 +@@ -78,7 +78,7 @@ + int m_VideoStream; + AVFormatContext* m_pFormatContext; + AVCodecContext* m_pVideoCodecContext; +- AVCodec* m_pVideoCodec; ++ const AVCodec* m_pVideoCodec; + AVFilterGraph* m_pFilterGraph; + AVFilterContext* m_pFilterSource; + AVFilterContext* m_pFilterSink; diff --git a/srcpkgs/ffmpegthumbnailer/template b/srcpkgs/ffmpegthumbnailer/template index 039eea7622b3..35d546018d12 100644 --- a/srcpkgs/ffmpegthumbnailer/template +++ b/srcpkgs/ffmpegthumbnailer/template @@ -1,7 +1,7 @@ # Template file for 'ffmpegthumbnailer' pkgname=ffmpegthumbnailer version=2.2.2 -revision=1 +revision=2 build_style=cmake hostmakedepends="pkg-config" makedepends="libpng-devel libjpeg-turbo-devel ffmpeg-devel" @@ -9,8 +9,8 @@ depends="ffmpeg" short_desc="Lightweight video thumbnailer" maintainer="Orphaned " license="GPL-2.0-or-later" -homepage="https://github.com/dirkvdb/${pkgname}" -distfiles="${homepage}/releases/download/${version}/${pkgname}-${version}.tar.bz2" +homepage="https://github.com/dirkvdb" +distfiles="${homepage}/${pkgname}/releases/download/${version}/${pkgname}-${version}.tar.bz2" checksum=1cb24059c38223f657b300c84dd80491b7040d4b69471c4fea69be862bc99b5b post_install() { From 95cfc4ff7f2df5015541365b4e63bcbd81b0c633 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:47 -0400 Subject: [PATCH 032/113] ffmpegthumbs: revbump for ffmpeg-6.0 --- srcpkgs/ffmpegthumbs/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/ffmpegthumbs/template b/srcpkgs/ffmpegthumbs/template index 5f0b9414dada..11b88193528f 100644 --- a/srcpkgs/ffmpegthumbs/template +++ b/srcpkgs/ffmpegthumbs/template @@ -1,7 +1,7 @@ # Template file for 'ffmpegthumbs' pkgname=ffmpegthumbs version=22.12.1 -revision=1 +revision=2 build_style=cmake hostmakedepends="extra-cmake-modules kcoreaddons kconfig-devel pkg-config qt5-host-tools qt5-qmake gettext" From 96cbfd395949478b017fe42072d30f7a7e2cf12f Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:47 -0400 Subject: [PATCH 033/113] ffms2: revbump for ffmpeg-6.0 --- srcpkgs/ffms2/patches/ffmpeg5.patch | 424 ++++++++++++++++++++++++++++ srcpkgs/ffms2/template | 2 +- 2 files changed, 425 insertions(+), 1 deletion(-) create mode 100644 srcpkgs/ffms2/patches/ffmpeg5.patch diff --git a/srcpkgs/ffms2/patches/ffmpeg5.patch b/srcpkgs/ffms2/patches/ffmpeg5.patch new file mode 100644 index 000000000000..1479fabcafcb --- /dev/null +++ b/srcpkgs/ffms2/patches/ffmpeg5.patch @@ -0,0 +1,424 @@ +From 45673149e9a2f5586855ad472e3059084eaa36b1 Mon Sep 17 00:00:00 2001 +From: Derek Buitenhuis +Date: Tue, 4 May 2021 14:41:21 +0100 +Subject: [PATCH] Use auto for AVCodec + +The geniuses over at FFmpeg decided to constify this API, so old +versions of the library will return AVCodec *, while new versions +of the libary will return const AVCodec *, which, in C++, are not +OK to convert between. + +Rather than use some macro hell in ffmscompat.h, we can work around +this by using auto. + +Gross. + +Signed-off-by: Derek Buitenhuis +--- + src/core/audiosource.cpp | 2 +- + src/core/indexing.cpp | 6 +++--- + src/core/videosource.cpp | 2 +- + 3 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/core/audiosource.cpp b/src/core/audiosource.cpp +index e4ce97c..ac09666 100644 +--- a/src/core/audiosource.cpp ++++ b/src/core/audiosource.cpp +@@ -469,7 +469,7 @@ void FFMS_AudioSource::OpenFile() { + + LAVFOpenFile(SourceFile.c_str(), FormatContext, TrackNumber); + +- AVCodec *Codec = avcodec_find_decoder(FormatContext->streams[TrackNumber]->codecpar->codec_id); ++ auto *Codec = avcodec_find_decoder(FormatContext->streams[TrackNumber]->codecpar->codec_id); + if (Codec == nullptr) + throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC, + "Audio codec not found"); +diff --git a/src/core/indexing.cpp b/src/core/indexing.cpp +index e547c5a..59fb4e8 100644 +--- a/src/core/indexing.cpp ++++ b/src/core/indexing.cpp +@@ -384,7 +384,7 @@ FFMS_TrackType FFMS_Indexer::GetTrackType(int Track) { + } + + const char *FFMS_Indexer::GetTrackCodec(int Track) { +- AVCodec *codec = avcodec_find_decoder(FormatContext->streams[Track]->codecpar->codec_id); ++ auto *codec = avcodec_find_decoder(FormatContext->streams[Track]->codecpar->codec_id); + return codec ? codec->name : nullptr; + } + +@@ -402,7 +402,7 @@ FFMS_Index *FFMS_Indexer::DoIndexing() { + UseDTS); + + if (IndexMask.count(i) && FormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { +- AVCodec *VideoCodec = avcodec_find_decoder(FormatContext->streams[i]->codecpar->codec_id); ++ auto *VideoCodec = avcodec_find_decoder(FormatContext->streams[i]->codecpar->codec_id); + if (!VideoCodec) { + FormatContext->streams[i]->discard = AVDISCARD_ALL; + IndexMask.erase(i); +@@ -433,7 +433,7 @@ FFMS_Index *FFMS_Indexer::DoIndexing() { + IndexMask.insert(i); + } + } else if (IndexMask.count(i) && FormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { +- AVCodec *AudioCodec = avcodec_find_decoder(FormatContext->streams[i]->codecpar->codec_id); ++ auto *AudioCodec = avcodec_find_decoder(FormatContext->streams[i]->codecpar->codec_id); + if (AudioCodec == nullptr) + throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_UNSUPPORTED, + "Audio codec not found"); +diff --git a/src/core/videosource.cpp b/src/core/videosource.cpp +index b889970..8956c22 100644 +--- a/src/core/videosource.cpp ++++ b/src/core/videosource.cpp +@@ -171,7 +171,7 @@ FFMS_VideoSource::FFMS_VideoSource(const char *SourceFile, FFMS_Index &Index, in + + LAVFOpenFile(SourceFile, FormatContext, VideoTrack); + +- AVCodec *Codec = avcodec_find_decoder(FormatContext->streams[VideoTrack]->codecpar->codec_id); ++ auto *Codec = avcodec_find_decoder(FormatContext->streams[VideoTrack]->codecpar->codec_id); + if (Codec == nullptr) + throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC, + "Video codec not found"); +-- +2.40.0 + +From 96cbf38ea9381829a1314f432a2c60495dcefaad Mon Sep 17 00:00:00 2001 +From: Derek Buitenhuis +Date: Tue, 4 May 2021 14:12:41 +0100 +Subject: [PATCH] all: Update AVPacket API usage + +AVPackets must all be on the heap now, since it is no longer +part of the libav* ABI. + +Signed-off-by: Derek Buitenhuis +--- + src/core/audiosource.cpp | 16 ++++++---- + src/core/indexing.cpp | 63 ++++++++++++++++++++++------------------ + src/core/indexing.h | 4 +-- + src/core/utils.cpp | 6 ---- + src/core/utils.h | 1 - + src/core/videosource.cpp | 30 ++++++++++--------- + 6 files changed, 64 insertions(+), 56 deletions(-) + +diff --git a/src/core/audiosource.cpp b/src/core/audiosource.cpp +index 37cf9ae..e4ce97c 100644 +--- a/src/core/audiosource.cpp ++++ b/src/core/audiosource.cpp +@@ -285,10 +285,15 @@ FFMS_AudioSource::AudioBlock *FFMS_AudioSource::CacheBlock(CacheIterator &pos) { + int FFMS_AudioSource::DecodeNextBlock(CacheIterator *pos) { + CurrentFrame = &Frames[PacketNumber]; + +- AVPacket Packet; +- if (!ReadPacket(&Packet)) ++ AVPacket *Packet = av_packet_alloc(); ++ if (!Packet) ++ throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_ALLOCATION_FAILED, ++ "Could not allocate packet."); ++ if (!ReadPacket(Packet)) { ++ av_packet_free(&Packet); + throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_UNKNOWN, + "ReadPacket unexpectedly failed to read a packet"); ++ } + + // ReadPacket may have changed the packet number + CurrentFrame = &Frames[PacketNumber]; +@@ -297,8 +302,9 @@ int FFMS_AudioSource::DecodeNextBlock(CacheIterator *pos) { + int NumberOfSamples = 0; + AudioBlock *CachedBlock = nullptr; + +- int Ret = avcodec_send_packet(CodecContext, &Packet); +- av_packet_unref(&Packet); ++ int Ret = avcodec_send_packet(CodecContext, Packet); ++ av_packet_unref(Packet); ++ av_packet_free(&Packet); + + av_frame_unref(DecodeFrame); + Ret = avcodec_receive_frame(CodecContext, DecodeFrame); +@@ -513,8 +519,6 @@ void FFMS_AudioSource::Seek() { + } + + bool FFMS_AudioSource::ReadPacket(AVPacket *Packet) { +- InitNullPacket(*Packet); +- + while (av_read_frame(FormatContext, Packet) >= 0) { + if (Packet->stream_index == TrackNumber) { + // Required because not all audio packets, especially in ogg, have a pts. Use the previous valid packet's pts instead. +diff --git a/src/core/indexing.cpp b/src/core/indexing.cpp +index 23fb95b..e547c5a 100644 +--- a/src/core/indexing.cpp ++++ b/src/core/indexing.cpp +@@ -320,7 +320,7 @@ void FFMS_Indexer::CheckAudioProperties(int Track, AVCodecContext *Context) { + } + } + +-void FFMS_Indexer::ParseVideoPacket(SharedAVContext &VideoContext, AVPacket &pkt, int *RepeatPict, ++void FFMS_Indexer::ParseVideoPacket(SharedAVContext &VideoContext, AVPacket *pkt, int *RepeatPict, + int *FrameType, bool *Invisible, enum AVPictureStructure *LastPicStruct) { + if (VideoContext.Parser) { + uint8_t *OB; +@@ -330,8 +330,8 @@ void FFMS_Indexer::ParseVideoPacket(SharedAVContext &VideoContext, AVPacket &pkt + av_parser_parse2(VideoContext.Parser, + VideoContext.CodecContext, + &OB, &OBSize, +- pkt.data, pkt.size, +- pkt.pts, pkt.dts, pkt.pos); ++ pkt->data, pkt->size, ++ pkt->pts, pkt->dts, pkt->pos); + + // H.264 (PAFF) and HEVC may have one field per packet, so we need to track + // when we have a full or half frame available, and mark one of them as +@@ -351,15 +351,15 @@ void FFMS_Indexer::ParseVideoPacket(SharedAVContext &VideoContext, AVPacket &pkt + + *RepeatPict = VideoContext.Parser->repeat_pict; + *FrameType = VideoContext.Parser->pict_type; +- *Invisible = (IncompleteFrame || VideoContext.Parser->repeat_pict < 0 || (pkt.flags & AV_PKT_FLAG_DISCARD)); ++ *Invisible = (IncompleteFrame || VideoContext.Parser->repeat_pict < 0 || (pkt->flags & AV_PKT_FLAG_DISCARD)); + } else { +- *Invisible = !!(pkt.flags & AV_PKT_FLAG_DISCARD); ++ *Invisible = !!(pkt->flags & AV_PKT_FLAG_DISCARD); + } + + if (VideoContext.CodecContext->codec_id == AV_CODEC_ID_VP8) +- ParseVP8(pkt.data[0], Invisible, FrameType); ++ ParseVP8(pkt->data[0], Invisible, FrameType); + else if (VideoContext.CodecContext->codec_id == AV_CODEC_ID_VP9) +- ParseVP9(pkt.data[0], Invisible, FrameType); ++ ParseVP9(pkt->data[0], Invisible, FrameType); + } + + void FFMS_Indexer::Free() { +@@ -458,32 +458,36 @@ FFMS_Index *FFMS_Indexer::DoIndexing() { + } + } + +- AVPacket Packet; +- InitNullPacket(Packet); ++ AVPacket *Packet = av_packet_alloc(); ++ if (!Packet) ++ throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_ALLOCATION_FAILED, ++ "Could not allocate packet."); + std::vector LastValidTS(FormatContext->nb_streams, AV_NOPTS_VALUE); + + int64_t filesize = avio_size(FormatContext->pb); + enum AVPictureStructure LastPicStruct = AV_PICTURE_STRUCTURE_UNKNOWN; +- while (av_read_frame(FormatContext, &Packet) >= 0) { ++ while (av_read_frame(FormatContext, Packet) >= 0) { + // Update progress + // FormatContext->pb can apparently be NULL when opening images. + if (IC && FormatContext->pb) { +- if ((*IC)(FormatContext->pb->pos, filesize, ICPrivate)) ++ if ((*IC)(FormatContext->pb->pos, filesize, ICPrivate)) { ++ av_packet_free(&Packet); + throw FFMS_Exception(FFMS_ERROR_CANCELLED, FFMS_ERROR_USER, + "Cancelled by user"); ++ } + } +- if (!IndexMask.count(Packet.stream_index)) { +- av_packet_unref(&Packet); ++ if (!IndexMask.count(Packet->stream_index)) { ++ av_packet_unref(Packet); + continue; + } + +- int Track = Packet.stream_index; ++ int Track = Packet->stream_index; + FFMS_Track &TrackInfo = (*TrackIndices)[Track]; +- bool KeyFrame = !!(Packet.flags & AV_PKT_FLAG_KEY); ++ bool KeyFrame = !!(Packet->flags & AV_PKT_FLAG_KEY); + ReadTS(Packet, LastValidTS[Track], (*TrackIndices)[Track].UseDTS); + + if (FormatContext->streams[Track]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { +- int64_t PTS = TrackInfo.UseDTS ? Packet.dts : Packet.pts; ++ int64_t PTS = TrackInfo.UseDTS ? Packet->dts : Packet->pts; + if (PTS == AV_NOPTS_VALUE) { + // VPx alt-refs are output as packets which lack timestmps or durations, since + // they are invisible. Currently, the timestamp mangling code in libavformat +@@ -495,9 +499,11 @@ FFMS_Index *FFMS_Indexer::DoIndexing() { + // FFMS2 currently sorts packets by PTS, which will break decoding, otherwise. + bool HasAltRefs = (FormatContext->streams[Track]->codecpar->codec_id == AV_CODEC_ID_VP8 || + FormatContext->streams[Track]->codecpar->codec_id == AV_CODEC_ID_VP9); +- if (Packet.duration == 0 && !HasAltRefs) ++ if (Packet->duration == 0 && !HasAltRefs) { ++ av_packet_free(&Packet); + throw FFMS_Exception(FFMS_ERROR_INDEXING, FFMS_ERROR_PARSER, + "Invalid packet pts, dts, and duration"); ++ } + + if (TrackInfo.empty()) + PTS = 0; +@@ -513,7 +519,7 @@ FFMS_Index *FFMS_Indexer::DoIndexing() { + ParseVideoPacket(AVContexts[Track], Packet, &RepeatPict, &FrameType, &Invisible, &LastPicStruct); + + TrackInfo.AddVideoFrame(PTS, RepeatPict, KeyFrame, +- FrameType, Packet.pos, Invisible); ++ FrameType, Packet->pos, Invisible); + } else if (FormatContext->streams[Track]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + // For video seeking timestamps are used only if all packets have + // timestamps, while for audio they're used if any have timestamps, +@@ -522,28 +528,29 @@ FFMS_Index *FFMS_Indexer::DoIndexing() { + TrackInfo.HasTS = true; + + int64_t StartSample = AVContexts[Track].CurrentSample; +- uint32_t SampleCount = IndexAudioPacket(Track, &Packet, AVContexts[Track], *TrackIndices); ++ uint32_t SampleCount = IndexAudioPacket(Track, Packet, AVContexts[Track], *TrackIndices); + TrackInfo.SampleRate = AVContexts[Track].CodecContext->sample_rate; + + TrackInfo.AddAudioFrame(LastValidTS[Track], +- StartSample, SampleCount, KeyFrame, Packet.pos, Packet.flags & AV_PKT_FLAG_DISCARD); ++ StartSample, SampleCount, KeyFrame, Packet->pos, Packet->flags & AV_PKT_FLAG_DISCARD); + } + +- if (!(Packet.flags & AV_PKT_FLAG_DISCARD)) +- TrackInfo.LastDuration = Packet.duration; ++ if (!(Packet->flags & AV_PKT_FLAG_DISCARD)) ++ TrackInfo.LastDuration = Packet->duration; + +- av_packet_unref(&Packet); ++ av_packet_unref(Packet); + } ++ av_packet_free(&Packet); + + TrackIndices->Finalize(AVContexts, FormatContext->iformat->name); + return TrackIndices.release(); + } + +-void FFMS_Indexer::ReadTS(const AVPacket &Packet, int64_t &TS, bool &UseDTS) { +- if (!UseDTS && Packet.pts != AV_NOPTS_VALUE) +- TS = Packet.pts; ++void FFMS_Indexer::ReadTS(const AVPacket *Packet, int64_t &TS, bool &UseDTS) { ++ if (!UseDTS && Packet->pts != AV_NOPTS_VALUE) ++ TS = Packet->pts; + if (TS == AV_NOPTS_VALUE) + UseDTS = true; +- if (UseDTS && Packet.dts != AV_NOPTS_VALUE) +- TS = Packet.dts; ++ if (UseDTS && Packet->dts != AV_NOPTS_VALUE) ++ TS = Packet->dts; + } +diff --git a/src/core/indexing.h b/src/core/indexing.h +index 3cfc3c3..5c06868 100644 +--- a/src/core/indexing.h ++++ b/src/core/indexing.h +@@ -80,10 +80,10 @@ private: + int64_t Filesize; + uint8_t Digest[20]; + +- void ReadTS(const AVPacket &Packet, int64_t &TS, bool &UseDTS); ++ void ReadTS(const AVPacket *Packet, int64_t &TS, bool &UseDTS); + void CheckAudioProperties(int Track, AVCodecContext *Context); + uint32_t IndexAudioPacket(int Track, AVPacket *Packet, SharedAVContext &Context, FFMS_Index &TrackIndices); +- void ParseVideoPacket(SharedAVContext &VideoContext, AVPacket &pkt, int *RepeatPict, int *FrameType, bool *Invisible, enum AVPictureStructure *LastPicStruct); ++ void ParseVideoPacket(SharedAVContext &VideoContext, AVPacket *pkt, int *RepeatPict, int *FrameType, bool *Invisible, enum AVPictureStructure *LastPicStruct); + void Free(); + public: + FFMS_Indexer(const char *Filename); +diff --git a/src/core/utils.cpp b/src/core/utils.cpp +index ce67533..8a2e997 100644 +--- a/src/core/utils.cpp ++++ b/src/core/utils.cpp +@@ -62,12 +62,6 @@ void ClearErrorInfo(FFMS_ErrorInfo *ErrorInfo) { + } + } + +-void InitNullPacket(AVPacket &pkt) { +- av_init_packet(&pkt); +- pkt.data = nullptr; +- pkt.size = 0; +-} +- + void FillAP(FFMS_AudioProperties &AP, AVCodecContext *CTX, FFMS_Track &Frames) { + AP.SampleFormat = static_cast(av_get_packed_sample_fmt(CTX->sample_fmt)); + AP.BitsPerSample = av_get_bytes_per_sample(CTX->sample_fmt) * 8; +diff --git a/src/core/utils.h b/src/core/utils.h +index 9819dc7..003ab79 100644 +--- a/src/core/utils.h ++++ b/src/core/utils.h +@@ -58,7 +58,6 @@ std::unique_ptr make_unique(Args&&... args) { + } + + void ClearErrorInfo(FFMS_ErrorInfo *ErrorInfo); +-void InitNullPacket(AVPacket &pkt); + void FillAP(FFMS_AudioProperties &AP, AVCodecContext *CTX, FFMS_Track &Frames); + + void LAVFOpenFile(const char *SourceFile, AVFormatContext *&FormatContext, int Track); +diff --git a/src/core/videosource.cpp b/src/core/videosource.cpp +index 06bd161..b889970 100644 +--- a/src/core/videosource.cpp ++++ b/src/core/videosource.cpp +@@ -673,30 +673,34 @@ void FFMS_VideoSource::DecodeNextFrame(int64_t &AStartTime, int64_t &Pos) { + if (HasPendingDelayedFrames()) + return; + +- AVPacket Packet; +- InitNullPacket(Packet); +- +- while (ReadFrame(&Packet) >= 0) { +- if (Packet.stream_index != VideoTrack) { +- av_packet_unref(&Packet); ++ AVPacket *Packet = av_packet_alloc(); ++ if (!Packet) ++ throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_ALLOCATION_FAILED, ++ "Could not allocate packet."); ++ ++ while (ReadFrame(Packet) >= 0) { ++ if (Packet->stream_index != VideoTrack) { ++ av_packet_unref(Packet); + continue; + } + + if (AStartTime < 0) +- AStartTime = Frames.UseDTS ? Packet.dts : Packet.pts; ++ AStartTime = Frames.UseDTS ? Packet->dts : Packet->pts; + + if (Pos < 0) +- Pos = Packet.pos; ++ Pos = Packet->pos; + +- bool FrameFinished = DecodePacket(&Packet); +- av_packet_unref(&Packet); +- if (FrameFinished) ++ bool FrameFinished = DecodePacket(Packet); ++ av_packet_unref(Packet); ++ if (FrameFinished) { ++ av_packet_free(&Packet); + return; ++ } + } + + // Flush final frames +- InitNullPacket(Packet); +- DecodePacket(&Packet); ++ DecodePacket(Packet); ++ av_packet_free(&Packet); + } + + bool FFMS_VideoSource::SeekTo(int n, int SeekOffset) { +-- +2.40.0 + +From bf9e03e9e08534c024e5a744a6437c4aac160201 Mon Sep 17 00:00:00 2001 +From: Derek Buitenhuis +Date: Tue, 4 May 2021 14:20:47 +0100 +Subject: [PATCH 2/3] configure: Remove deprecated API use + +Signed-off-by: Derek Buitenhuis +--- + configure.ac | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index b35ef80bc..d19714d0f 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -102,10 +102,10 @@ CFLAGS="$_CFLAGS $FFMPEG_CFLAGS" + + AC_DEFUN([TEST_FFMPEG], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +- #include ++ #include + #include + ]],[[ +- avcodec_register_all(); ++ avformat_network_init(); + swscale_version(); + ]])], [eval $1=yes], [eval $1=no]) + ]) + diff --git a/srcpkgs/ffms2/template b/srcpkgs/ffms2/template index 68e8a0c14bce..2acfadac44b3 100644 --- a/srcpkgs/ffms2/template +++ b/srcpkgs/ffms2/template @@ -1,7 +1,7 @@ # Template file for 'ffms2' pkgname=ffms2 version=2.40 -revision=1 +revision=2 build_style=gnu-configure configure_args="--enable-shared --disable-static" hostmakedepends="pkg-config autoconf automake libtool" From e874041f3f3354e6d2ec4cd3b335adbae9a02236 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:47 -0400 Subject: [PATCH 034/113] freerdp: revbump for ffmpeg-6.0 --- .../freerdp/patches/ffmpeg6_aa2cb9aa.patch | 42 +++++++++++++++++++ srcpkgs/freerdp/template | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 srcpkgs/freerdp/patches/ffmpeg6_aa2cb9aa.patch diff --git a/srcpkgs/freerdp/patches/ffmpeg6_aa2cb9aa.patch b/srcpkgs/freerdp/patches/ffmpeg6_aa2cb9aa.patch new file mode 100644 index 000000000000..a4324da3a882 --- /dev/null +++ b/srcpkgs/freerdp/patches/ffmpeg6_aa2cb9aa.patch @@ -0,0 +1,42 @@ +From aa2cb9aa5ff5562433598ba168a466e0752bca0e Mon Sep 17 00:00:00 2001 +From: akallabeth +Date: Tue, 14 Feb 2023 07:48:54 +0100 +Subject: [PATCH] Fixed #8686: Update h264 to use new FFMPEG API + +--- + channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c | 2 ++ + libfreerdp/codec/h264_ffmpeg.c | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c +index 339462d865f..beea80b7a1e 100644 +--- a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c ++++ b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c +@@ -239,8 +239,10 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP + } + } + ++#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 18, 100) + if (mdecoder->codec->capabilities & AV_CODEC_CAP_TRUNCATED) + mdecoder->codec_context->flags |= AV_CODEC_FLAG_TRUNCATED; ++#endif + + return TRUE; + } +diff --git a/libfreerdp/codec/h264_ffmpeg.c b/libfreerdp/codec/h264_ffmpeg.c +index 8a23db2473c..896a333019b 100644 +--- a/libfreerdp/codec/h264_ffmpeg.c ++++ b/libfreerdp/codec/h264_ffmpeg.c +@@ -615,10 +615,12 @@ static BOOL libavcodec_init(H264_CONTEXT* h264) + goto EXCEPTION; + } + ++#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 18, 100) + if (sys->codecDecoder->capabilities & AV_CODEC_CAP_TRUNCATED) + { + sys->codecDecoderContext->flags |= AV_CODEC_FLAG_TRUNCATED; + } ++#endif + + #ifdef WITH_VAAPI + diff --git a/srcpkgs/freerdp/template b/srcpkgs/freerdp/template index 25e8aa9677f0..4d51c8189902 100644 --- a/srcpkgs/freerdp/template +++ b/srcpkgs/freerdp/template @@ -1,7 +1,7 @@ # Template file for 'freerdp' pkgname=freerdp version=2.10.0 -revision=1 +revision=2 build_style=cmake configure_args="-DWITH_ALSA=ON -DWITH_CUPS=OFF -DWITH_FFMPEG=ON -DWITH_GSTREAMER_0_10=OFF -DWITH_GSTREAMER_1_0=OFF -DWITH_JPEG=ON From 8c88a89ec931b6ea742d7fada33746d1f4e29937 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:47 -0400 Subject: [PATCH 035/113] gerbera: revbump for ffmpeg-6.0 --- srcpkgs/gerbera/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/gerbera/template b/srcpkgs/gerbera/template index ae14f35c767c..2dc0ac0ce03b 100644 --- a/srcpkgs/gerbera/template +++ b/srcpkgs/gerbera/template @@ -1,7 +1,7 @@ # Template file for 'gerbera' pkgname=gerbera version=1.12.1 -revision=1 +revision=2 build_style=cmake configure_args="-DWITH_SYSTEMD=0 -DWITH_AVCODEC=1" hostmakedepends="pkg-config" From 228fe1e6a1512fdc694bed33de3f6a8d90e1777a Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:47 -0400 Subject: [PATCH 036/113] goldendict: revbump for ffmpeg-6.0 --- srcpkgs/goldendict/patches/ffmpeg5.patch | 232 +++++++++++++++++++++++ srcpkgs/goldendict/template | 4 +- 2 files changed, 234 insertions(+), 2 deletions(-) create mode 100644 srcpkgs/goldendict/patches/ffmpeg5.patch diff --git a/srcpkgs/goldendict/patches/ffmpeg5.patch b/srcpkgs/goldendict/patches/ffmpeg5.patch new file mode 100644 index 000000000000..7cfc98ada368 --- /dev/null +++ b/srcpkgs/goldendict/patches/ffmpeg5.patch @@ -0,0 +1,232 @@ +From 03bbe01b79a1f07a6780cb60f23a087104c5d77b Mon Sep 17 00:00:00 2001 +From: Abs62 +Date: Fri, 30 Mar 2018 22:53:24 +0300 +Subject: [PATCH] Fix warnings while compile with FFMpeg 3.4.2 (issue #978) + +--- + ffmpegaudio.cc | 68 +++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 62 insertions(+), 6 deletions(-) + +diff --git a/ffmpegaudio.cc b/ffmpegaudio.cc +index ed1172bdd..56e8f788e 100644 +--- a/ffmpegaudio.cc ++++ b/ffmpegaudio.cc +@@ -91,6 +91,7 @@ struct DecoderContext + QByteArray audioData_; + QDataStream audioDataStream_; + AVFormatContext * formatContext_; ++ AVCodec * codec_; + AVCodecContext * codecContext_; + AVIOContext * avioContext_; + AVStream * audioStream_; +@@ -114,6 +115,7 @@ DecoderContext::DecoderContext( QByteArray const & audioData, QAtomicInt & isCan + audioData_( audioData ), + audioDataStream_( audioData_ ), + formatContext_( NULL ), ++ codec_( NULL ), + codecContext_( NULL ), + avioContext_( NULL ), + audioStream_( NULL ), +@@ -143,7 +145,11 @@ bool DecoderContext::openCodec( QString & errorString ) + return false; + } + ++#if LIBAVCODEC_VERSION_MAJOR < 56 || ( LIBAVCODEC_VERSION_MAJOR == 56 && LIBAVCODEC_VERSION_MINOR < 56 ) + unsigned char * avioBuffer = ( unsigned char * )av_malloc( kBufferSize + FF_INPUT_BUFFER_PADDING_SIZE ); ++#else ++ unsigned char * avioBuffer = ( unsigned char * )av_malloc( kBufferSize + AV_INPUT_BUFFER_PADDING_SIZE ); ++#endif + if ( !avioBuffer ) + { + errorString = QObject::tr( "av_malloc() failed." ); +@@ -186,7 +192,11 @@ bool DecoderContext::openCodec( QString & errorString ) + // Find audio stream, use the first audio stream if available + for ( unsigned i = 0; i < formatContext_->nb_streams; i++ ) + { ++#if LIBAVCODEC_VERSION_MAJOR < 57 || ( LIBAVCODEC_VERSION_MAJOR == 57 && LIBAVCODEC_VERSION_MINOR < 33 ) + if ( formatContext_->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO ) ++#else ++ if ( formatContext_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ) ++#endif + { + audioStream_ = formatContext_->streams[i]; + break; +@@ -198,22 +208,38 @@ bool DecoderContext::openCodec( QString & errorString ) + return false; + } + ++#if LIBAVCODEC_VERSION_MAJOR < 57 || ( LIBAVCODEC_VERSION_MAJOR == 57 && LIBAVCODEC_VERSION_MINOR < 33 ) + codecContext_ = audioStream_->codec; +- AVCodec * codec = avcodec_find_decoder( codecContext_->codec_id ); +- if ( !codec ) ++ codec_ = avcodec_find_decoder( codecContext_->codec_id ); ++ if ( !codec_ ) + { + errorString = QObject::tr( "Codec [id: %1] not found." ).arg( codecContext_->codec_id ); + return false; + } ++#else ++ codec_ = avcodec_find_decoder( audioStream_->codecpar->codec_id ); ++ if ( !codec_ ) ++ { ++ errorString = QObject::tr( "Codec [id: %1] not found." ).arg( audioStream_->codecpar->codec_id ); ++ return false; ++ } ++ codecContext_ = avcodec_alloc_context3( codec_ ); ++ if ( !codecContext_ ) ++ { ++ errorString = QObject::tr( "avcodec_alloc_context3() failed." ); ++ return false; ++ } ++ avcodec_parameters_to_context( codecContext_, audioStream_->codecpar ); ++#endif + +- ret = avcodec_open2( codecContext_, codec, NULL ); ++ ret = avcodec_open2( codecContext_, codec_, NULL ); + if ( ret < 0 ) + { + errorString = QObject::tr( "avcodec_open2() failed: %1." ).arg( avErrorString( ret ) ); + return false; + } + +- av_log( NULL, AV_LOG_INFO, "Codec open: %s: channels: %d, rate: %d, format: %s\n", codec->long_name, ++ av_log( NULL, AV_LOG_INFO, "Codec open: %s: channels: %d, rate: %d, format: %s\n", codec_->long_name, + codecContext_->channels, codecContext_->sample_rate, av_get_sample_fmt_name( codecContext_->sample_fmt ) ); + return true; + } +@@ -252,10 +278,13 @@ void DecoderContext::closeCodec() + + // Closing a codec context without prior avcodec_open2() will result in + // a crash in ffmpeg +- if ( audioStream_ && audioStream_->codec && audioStream_->codec->codec ) ++ if ( audioStream_ && codecContext_ && codec_ ) + { + audioStream_->discard = AVDISCARD_ALL; +- avcodec_close( audioStream_->codec ); ++ avcodec_close( codecContext_ ); ++#if LIBAVCODEC_VERSION_MAJOR > 57 || ( LIBAVCODEC_VERSION_MAJOR == 57 && LIBAVCODEC_VERSION_MINOR >= 33 ) ++ avcodec_free_context( &codecContext_ ); ++#endif + } + + avformat_close_input( &formatContext_ ); +@@ -356,6 +385,7 @@ bool DecoderContext::play( QString & errorString ) + if ( packet.stream_index == audioStream_->index ) + { + AVPacket pack = packet; ++#if LIBAVCODEC_VERSION_MAJOR < 57 || ( LIBAVCODEC_VERSION_MAJOR == 57 && LIBAVCODEC_VERSION_MINOR < 37 ) + int gotFrame = 0; + do + { +@@ -370,6 +400,19 @@ bool DecoderContext::play( QString & errorString ) + pack.data += len; + } + while( pack.size > 0 ); ++#else ++ int ret = avcodec_send_packet( codecContext_, &pack ); ++ /* read all the output frames (in general there may be any number of them) */ ++ while( ret >= 0 ) ++ { ++ ret = avcodec_receive_frame( codecContext_, frame); ++ ++ if ( Qt4x5::AtomicInt::loadAcquire( isCancelled_ ) || ret < 0 ) ++ break; ++ ++ playFrame( frame ); ++ } ++#endif + } + // av_free_packet() must be called after each call to av_read_frame() + #if LIBAVCODEC_VERSION_MAJOR < 57 || ( LIBAVCODEC_VERSION_MAJOR == 57 && LIBAVCODEC_VERSION_MINOR < 7 ) +@@ -379,6 +422,7 @@ bool DecoderContext::play( QString & errorString ) + #endif + } + ++#if LIBAVCODEC_VERSION_MAJOR < 57 || ( LIBAVCODEC_VERSION_MAJOR == 57 && LIBAVCODEC_VERSION_MINOR < 37 ) + if ( !Qt4x5::AtomicInt::loadAcquire( isCancelled_ ) && + codecContext_->codec->capabilities & CODEC_CAP_DELAY ) + { +@@ -391,6 +435,18 @@ bool DecoderContext::play( QString & errorString ) + playFrame( frame ); + } + } ++#else ++ /* flush the decoder */ ++ av_init_packet( &packet ); ++ int ret = avcodec_send_packet(codecContext_, &packet ); ++ while( ret >= 0 ) ++ { ++ ret = avcodec_receive_frame(codecContext_, frame); ++ if ( Qt4x5::AtomicInt::loadAcquire( isCancelled_ ) || ret < 0 ) ++ break; ++ playFrame( frame ); ++ } ++#endif + + #if LIBAVCODEC_VERSION_MAJOR < 54 + av_free( frame ); +32 +srcpkgs/goldendict/patches/ffmpeg5-2.patch +Comment on this file +@@ -0,0 +1,32 @@ +From 966f4a8b78e6324b930e5a50f2bb930bd87e565e Mon Sep 17 00:00:00 2001 +From: Abs62 +Date: Fri, 27 Sep 2019 17:00:52 +0300 +Subject: [PATCH] FFmpeg player: Fix some crashes on broken files + +--- + ffmpegaudio.cc | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/ffmpegaudio.cc b/ffmpegaudio.cc +index 56e8f788e..415fc79cb 100644 +--- a/ffmpegaudio.cc ++++ b/ffmpegaudio.cc +@@ -51,7 +51,9 @@ AudioService & AudioService::instance() + + AudioService::AudioService() + { ++#if LIBAVFORMAT_VERSION_MAJOR < 58 || ( LIBAVFORMAT_VERSION_MAJOR == 58 && LIBAVFORMAT_VERSION_MINOR < 9 ) + av_register_all(); ++#endif + ao_initialize(); + } + +@@ -438,6 +440,8 @@ bool DecoderContext::play( QString & errorString ) + #else + /* flush the decoder */ + av_init_packet( &packet ); ++ packet.data = NULL; ++ packet.size = 0; + int ret = avcodec_send_packet(codecContext_, &packet ); + while( ret >= 0 ) + { +25 +srcpkgs/goldendict/patches/ffmpeg5-3.patch +Comment on this file +@@ -0,0 +1,25 @@ +From 8acb288c9e9bdb3c6bf2e803954dd3b6ac273c05 Mon Sep 17 00:00:00 2001 +From: Liao Junxuan +Date: Sun, 20 Feb 2022 12:28:05 +0800 +Subject: [PATCH] add support for ffmpeg 5.0 + +--- + ffmpegaudio.cc | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/ffmpegaudio.cc b/ffmpegaudio.cc +index d550f4a77..7948d2187 100644 +--- a/ffmpegaudio.cc ++++ b/ffmpegaudio.cc +@@ -94,7 +94,11 @@ struct DecoderContext + QByteArray audioData_; + QDataStream audioDataStream_; + AVFormatContext * formatContext_; ++#if LIBAVCODEC_VERSION_MAJOR < 59 + AVCodec * codec_; ++#else ++ const AVCodec * codec_; ++#endif + AVCodecContext * codecContext_; + AVIOContext * avioContext_; + AVStream * audioStream_; diff --git a/srcpkgs/goldendict/template b/srcpkgs/goldendict/template index f4a05759f693..97f44347b03a 100644 --- a/srcpkgs/goldendict/template +++ b/srcpkgs/goldendict/template @@ -1,7 +1,7 @@ # Template file for 'goldendict' pkgname=goldendict version=1.5.0 -revision=1 +revision=2 build_style=qmake configure_args="CONFIG+=zim_support goldendict.pro" hostmakedepends="qt5-qmake pkg-config qt5-host-tools" @@ -10,7 +10,7 @@ makedepends="tiff-devel qt5-devel libvorbis-devel zlib-devel qt5-webkit-devel lzo-devel bzip2-devel libao-devel qt5-svg-devel libeb-devel qt5-x11extras-devel ffmpeg-devel liblzma-devel qt5-multimedia-devel" -short_desc="A feature-rich dictionary lookup program" +short_desc="Feature-rich dictionary lookup program" maintainer="John " license="GPL-3.0-or-later" homepage="http://goldendict.org/" From 1092cab70eb702338fcda39458af3075a84989eb Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:47 -0400 Subject: [PATCH 037/113] gst-libav: revbump for ffmpeg-6.0 --- srcpkgs/gst-libav/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/gst-libav/template b/srcpkgs/gst-libav/template index 8c72fc3e97ee..04c39bff1489 100644 --- a/srcpkgs/gst-libav/template +++ b/srcpkgs/gst-libav/template @@ -1,7 +1,7 @@ # Template file for 'gst-libav' pkgname=gst-libav version=1.22.2 -revision=1 +revision=2 build_style=meson hostmakedepends="pkg-config yasm" makedepends="orc-devel gst-plugins-base1-devel ffmpeg-devel" From 795f01f1db35fdd65c2f12c21eb11782b02bf1d7 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:47 -0400 Subject: [PATCH 038/113] gst-plugins-bad1: revbump for ffmpeg-6.0 --- srcpkgs/gst-plugins-bad1/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/gst-plugins-bad1/template b/srcpkgs/gst-plugins-bad1/template index 77bf79981c20..5c158724a6c7 100644 --- a/srcpkgs/gst-plugins-bad1/template +++ b/srcpkgs/gst-plugins-bad1/template @@ -1,7 +1,7 @@ # Template file for 'gst-plugins-bad1' pkgname=gst-plugins-bad1 version=1.22.2 -revision=1 +revision=2 build_helper="gir" build_style=meson configure_args="-Dpackage-origin=https://voidlinux.org -Ddoc=disabled From 261cf2c0cf795d208590136485ca25ffb594fe12 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:47 -0400 Subject: [PATCH 039/113] gst-rtsp-server: revbump for ffmpeg-6.0 --- srcpkgs/gst-rtsp-server/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/gst-rtsp-server/template b/srcpkgs/gst-rtsp-server/template index 2f0c0c45ff82..980fd72cdd4c 100644 --- a/srcpkgs/gst-rtsp-server/template +++ b/srcpkgs/gst-rtsp-server/template @@ -1,7 +1,7 @@ # Template file for 'gst-rtsp-server' pkgname=gst-rtsp-server version=1.22.2 -revision=1 +revision=2 build_style=meson hostmakedepends="pkg-config python3" makedepends="glib-devel gst-plugins-bad1-devel gobject-introspection From 4ef9daeb5fc8471959e00ed95470411c36df2827 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:47 -0400 Subject: [PATCH 040/113] guvcview: update to 2.0.8. --- srcpkgs/guvcview/patches/fix-include.patch | 10 ++++++++++ srcpkgs/guvcview/template | 5 ++--- 2 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 srcpkgs/guvcview/patches/fix-include.patch diff --git a/srcpkgs/guvcview/patches/fix-include.patch b/srcpkgs/guvcview/patches/fix-include.patch new file mode 100644 index 000000000000..503c2af3b78c --- /dev/null +++ b/srcpkgs/guvcview/patches/fix-include.patch @@ -0,0 +1,10 @@ +--- a/guvcview/guvcview.c ++++ b/guvcview/guvcview.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include "gview.h" + #include "gviewv4l2core.h" diff --git a/srcpkgs/guvcview/template b/srcpkgs/guvcview/template index 345cf6006f24..86a7fd619612 100644 --- a/srcpkgs/guvcview/template +++ b/srcpkgs/guvcview/template @@ -1,8 +1,7 @@ # Template file for 'guvcview' pkgname=guvcview -version=2.0.7 +version=2.0.8 revision=1 -create_wrksrc=yes build_style=gnu-configure configure_args="--disable-static --disable-debian-menu" hostmakedepends="pkg-config intltool autoconf automake libtool glib-devel" @@ -14,7 +13,7 @@ maintainer="Orphaned " license="GPL-3.0-or-later" homepage="http://guvcview.sourceforge.net/" distfiles="${SOURCEFORGE_SITE}/${pkgname}/${pkgname}-src-${version}.tar.bz2" -checksum=f47d51fbd06e44eeaa1a82f4a153c927527c90d94514197a70b2956028cc8ad4 +checksum=a21f4e448286666cf27bafef5290cc953a0a1796b752e5bbe521266dc1230c81 post_patch() { sed '31a#include ' -i guvcview/guvcview.c From b24f0364f0539ceeeea254a809f8c8a196a65ca8 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:48 -0400 Subject: [PATCH 041/113] handbrake: update to 1.6.1 --- .../patches/fix-missing-x265-link-flag.patch | 11 ++++++----- .../handbrake/patches/libhb-vpl-include.patch | 15 +++++++++++++++ srcpkgs/handbrake/template | 17 ++++++++++------- 3 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 srcpkgs/handbrake/patches/libhb-vpl-include.patch diff --git a/srcpkgs/handbrake/patches/fix-missing-x265-link-flag.patch b/srcpkgs/handbrake/patches/fix-missing-x265-link-flag.patch index 26db03867a0c..d6bb2eda627a 100644 --- a/srcpkgs/handbrake/patches/fix-missing-x265-link-flag.patch +++ b/srcpkgs/handbrake/patches/fix-missing-x265-link-flag.patch @@ -1,14 +1,15 @@ --- a/gtk/configure.ac +++ b/gtk/configure.ac @@ -203,7 +203,7 @@ - + AM_CONDITIONAL([MINGW], [test "x$mingw_flag" = "xyes"]) - --HB_LIBS="$HB_LIBS -lhandbrake -lavformat -lavfilter -lavcodec -lavutil -ldav1d -lswresample -lpostproc -ldvdnav -ldvdread -lmp3lame -lvorbis -lvorbisenc -logg -lswscale -ltheoraenc -ltheoradec -lvpx -lz -lbz2 -lbluray -lass -lfontconfig -lfreetype -lxml2 -ljansson -lopus -lspeex -lturbojpeg -llzma -lzimg" -+HB_LIBS="$HB_LIBS -lhandbrake -lavformat -lavfilter -lavcodec -lavutil -ldav1d -lswresample -lpostproc -ldvdnav -ldvdread -lmp3lame -lvorbis -lvorbisenc -logg -lswscale -ltheoraenc -ltheoradec -lvpx -lz -lbz2 -lbluray -lass -lfontconfig -lfreetype -lxml2 -ljansson -lopus -lspeex -lturbojpeg -llzma -lzimg -ldl" + +-HB_LIBS="$HB_LIBS -lhandbrake -lavformat -lavfilter -lavcodec -lavutil -ldav1d -lswresample -lpostproc -ldvdnav -ldvdread -lmp3lame -lvorbis -lvorbisenc -logg -lswscale -ltheoraenc -ltheoradec -lvpx -lz -lbz2 -lbluray -lass -lfontconfig -lfreetype -lxml2 -ljansson -lopus -lspeex -lturbojpeg -llzma -lzimg -lSvtAv1Enc" ++HB_LIBS="$HB_LIBS -lhandbrake -lavformat -lavfilter -lavcodec -lavutil -ldav1d -lswresample -lpostproc -ldvdnav -ldvdread -lmp3lame -lvorbis -lvorbisenc -logg -lswscale -ltheoraenc -ltheoradec -lvpx -lz -lbz2 -lbluray -lass -lfontconfig -lfreetype -lxml2 -ljansson -lopus -lspeex -lturbojpeg -llzma -lzimg -lSvtAv1Enc -ldl" HB_CPPFLAGS="$HB_CPPFLAGS $HBINC" - + PKG_CHECK_MODULES([x264], [x264], sys_x264=yes, sys_x264=no) + --- a/test/module.defs +++ b/test/module.defs @@ -69,6 +69,9 @@ diff --git a/srcpkgs/handbrake/patches/libhb-vpl-include.patch b/srcpkgs/handbrake/patches/libhb-vpl-include.patch new file mode 100644 index 000000000000..298f9f4ab28f --- /dev/null +++ b/srcpkgs/handbrake/patches/libhb-vpl-include.patch @@ -0,0 +1,15 @@ +--- a/libhb/module.defs 2023-01-22 11:36:49.000000000 -0500 ++++ b/libhb/module.defs 2023-04-03 22:37:52.395467010 -0400 +@@ -46,11 +46,7 @@ + LIBHB.GCC.I += $(LIBHB.build/) $(CONTRIB.build/)include + + ifeq (1,$(FEATURE.qsv)) +- ifeq ($(HOST.system),freebsd)) +- LIBHB.GCC.I += $(LOCALBASE)/include/vpl +- else +- LIBHB.GCC.I += $(CONTRIB.build/)include/vpl +- endif ++ LIBHB.GCC.I += /usr/include/vpl + endif + + ifneq (,$(filter $(HOST.system),freebsd netbsd openbsd)) diff --git a/srcpkgs/handbrake/template b/srcpkgs/handbrake/template index ca5e4571e49c..c32cb1bfa31f 100644 --- a/srcpkgs/handbrake/template +++ b/srcpkgs/handbrake/template @@ -1,10 +1,10 @@ # Template file for 'handbrake' pkgname=handbrake -version=1.5.1 +version=1.6.1 revision=1 build_style=gnu-configure configure_args="--force --disable-gtk-update-checks --disable-df-fetch --harden - $(vopt_enable fdk_aac fdk-aac) $(vopt_enable nvenc)" + $(vopt_enable fdk_aac fdk-aac) $(vopt_enable nvenc) $(vopt_enable qsv)" make_build_args="-C ${XBPS_TRIPLET}" make_install_args="-C ${XBPS_TRIPLET}" hostmakedepends="automake cmake gettext-devel glib-devel intltool libtool m4 meson nasm pkg-config python3" @@ -12,8 +12,11 @@ makedepends="bzip2-devel ffmpeg-devel gst-plugins-base1-devel gtk+3-devel jansson-devel lame-devel libass-devel libbluray-devel libdav1d-devel libdvdnav-devel libdvdread-devel libgudev-devel libnuma-devel libsamplerate-devel libtheora-devel libvorbis-devel libvpx-devel libxml2-devel - opus-devel speex-devel x264-devel x265-devel zimg-devel + opus-devel speex-devel x264-devel x265-devel zimg-devel libsvt-av1-devel $(vopt_if fdk_aac fdk-aac-devel) + $(vopt_if qsv libva-devel) + $(vopt_if qsv libdrm-devel) + $(vopt_if qsv onevpl-devel) $(vopt_if nvenc nv-codec-headers)" depends="desktop-file-utils gst-plugins-good1 hicolor-icon-theme" short_desc="Multithreaded video transcoder" @@ -21,15 +24,15 @@ maintainer="Enno Boland " license="GPL-2.0-only" homepage="https://handbrake.fr/" distfiles="https://github.com/HandBrake/HandBrake/releases/download/${version}/HandBrake-${version}-source.tar.bz2" -checksum=3999fe06d5309c819799a73a968a8ec3840e7840c2b64af8f5cdb7fd8c9430f0 +checksum=94ccfe03db917a91650000c510f7fd53f844da19f19ad4b4be1b8f6bc31a8d4c nocross=yes -build_options="fdk_aac nvenc" +build_options="fdk_aac nvenc qsv" case "$XBPS_TARGET_MACHINE" in x86_64*|i686*) CFLAGS="-msse" - build_options_default="nvenc" + build_options_default="nvenc qsv" ;; esac @@ -37,7 +40,7 @@ pre_configure() { # use system libraries, don't download them rm -rf contrib/ for module in fdk-aac ffmpeg libbluray libdav1d libdvdnav libdvdread nvenc \ - x265 zimg; do + x265 zimg svt-av1 libvpl; do vsed -i "/MODULES += contrib\/${module}/d" make/include/main.defs done } From 8428634e81d946ec5f9459fb53d5150e9e25a9d9 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:48 -0400 Subject: [PATCH 042/113] hedgewars: revbump for ffmpeg4-4.4.3 --- srcpkgs/hedgewars/template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srcpkgs/hedgewars/template b/srcpkgs/hedgewars/template index 419f29b98b44..926fe4fe3e68 100644 --- a/srcpkgs/hedgewars/template +++ b/srcpkgs/hedgewars/template @@ -1,13 +1,13 @@ # Template file for 'hedgewars' pkgname=hedgewars version=1.0.2 -revision=1 +revision=2 build_style=cmake configure_args="-DNOSERVER=1 -DDATA_INSTALL_DIR=/usr/share/${pkgname} -DPHYSFS_SYSTEM=1 -DMINIMAL_FLAGS=1" make_cmd=make hostmakedepends="lua51 pkg-config qt5-qmake qt5-host-tools" -makedepends="ffmpeg-devel lua51-devel physfs-devel qt5-tools-devel SDL2_image-devel +makedepends="ffmpeg4-devel lua51-devel physfs-devel qt5-tools-devel SDL2_image-devel SDL2_mixer-devel SDL2_net-devel SDL2_ttf-devel" depends="libfreeglut" short_desc="Funny turn-based artillery game, featuring fighting Hedgehogs!" From 574330a056113b2bca65a69c14f230b9ba7feebb Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:48 -0400 Subject: [PATCH 043/113] idjc: revbump for ffmpeg4-4.4.3 --- srcpkgs/idjc/template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srcpkgs/idjc/template b/srcpkgs/idjc/template index df60318b3db9..36a75baf597c 100644 --- a/srcpkgs/idjc/template +++ b/srcpkgs/idjc/template @@ -1,11 +1,11 @@ # Template file for 'idjc' pkgname=idjc version=0.9.1 -revision=3 +revision=4 build_style=gnu-configure hostmakedepends="pkg-config git python3 automake gettext-devel libtool" makedepends="libvorbis-devel libogg-devel jack-devel libsamplerate-devel - libflac-devel libsndfile-devel mpg123-devel ffmpeg-devel speex-devel + libflac-devel libsndfile-devel mpg123-devel ffmpeg4-devel speex-devel glib-devel pixman-devel lame-devel python3-gobject-devel libshout-idjc-devel opus-devel twolame-devel python3-mutagen python3-devel" depends="python3-gobject python3-mutagen desktop-file-utils shared-mime-info python3-dbus jack" From 6f9b42c7b7b39c3f7986d59aea8dc5c9f7eb8bb1 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:48 -0400 Subject: [PATCH 044/113] kfilemetadata5: revbump for ffmpeg-6.0 --- srcpkgs/kfilemetadata5/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/kfilemetadata5/template b/srcpkgs/kfilemetadata5/template index 4b91cf19f298..a3671a38ce59 100644 --- a/srcpkgs/kfilemetadata5/template +++ b/srcpkgs/kfilemetadata5/template @@ -1,7 +1,7 @@ # Template file for 'kfilemetadata5' pkgname=kfilemetadata5 version=5.107.0 -revision=1 +revision=2 build_style=cmake hostmakedepends="kcoreaddons extra-cmake-modules pkg-config qt5-host-tools qt5-qmake gettext kcoreaddons python3" From d1bc4a76ed23f9f37afb4f94bf8ca326e7ed8f2c Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:48 -0400 Subject: [PATCH 045/113] kid3: revbump for ffmpeg-6.0 --- srcpkgs/kid3/patches/ffmpeg5.patch | 17 +++++++++++++++++ srcpkgs/kid3/template | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 srcpkgs/kid3/patches/ffmpeg5.patch diff --git a/srcpkgs/kid3/patches/ffmpeg5.patch b/srcpkgs/kid3/patches/ffmpeg5.patch new file mode 100644 index 000000000000..135fc50e07c9 --- /dev/null +++ b/srcpkgs/kid3/patches/ffmpeg5.patch @@ -0,0 +1,17 @@ +# https://aur.archlinux.org/cgit/aur.git/diff/ffmpeg5.patch?h=kid3-cli&id=12410a74906612e7efc0ec8fbce739b4a0fef7e7 +diff --git a/src/plugins/acoustidimport/ffmpegfingerprintdecoder.cpp b/src/plugins/acoustidimport/ffmpegfingerprintdecoder.cpp +index e156d424..e12b9abd 100644 +--- a/src/plugins/acoustidimport/ffmpegfingerprintdecoder.cpp ++++ b/src/plugins/acoustidimport/ffmpegfingerprintdecoder.cpp +@@ -232,7 +232,11 @@ private: + friend class Format; + friend class Converter; + AVCodecContext* m_ptr; ++#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 0, 0) + AVCodec* m_impl; ++#else ++ const AVCodec* m_impl; ++#endif + AVFrame* m_frame; + bool m_opened; + }; diff --git a/srcpkgs/kid3/template b/srcpkgs/kid3/template index 456206d90e16..f32f9decb0e7 100644 --- a/srcpkgs/kid3/template +++ b/srcpkgs/kid3/template @@ -1,7 +1,7 @@ # Template file for 'kid3' pkgname=kid3 version=3.9.1 -revision=2 +revision=3 build_style=cmake configure_args="-DWITH_APPS='CLI;$(vopt_if KDE KDE Qt)' -DWITH_DOCBOOKDIR=/usr/share/xsl/docbook -DWITH_FLAC=$(vopt_if flac ON OFF) From 54376ca79080ef08b10ed751ee48ea8a218405ab Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:48 -0400 Subject: [PATCH 046/113] kodi: revbump for ffmpeg4-4.4.3 --- srcpkgs/kodi/template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srcpkgs/kodi/template b/srcpkgs/kodi/template index 8057964d78a3..6cc1874be7ba 100644 --- a/srcpkgs/kodi/template +++ b/srcpkgs/kodi/template @@ -1,7 +1,7 @@ # Template file for 'kodi' pkgname=kodi version=19.4 -revision=6 +revision=7 _codename="Matrix" build_style=cmake configure_args="-DWITH_FFMPEG=/usr -DENABLE_LDGOLD=OFF @@ -54,7 +54,7 @@ makedepends=" libmad-devel fontconfig-devel libXinerama-devel libsamplerate-devel libmms-devel enca-devel boost-devel libcurl-devel libva-devel libvdpau-devel libass-devel libbluetooth-devel yajl-devel libplist-devel librtmp-devel tinyxml-devel - taglib-devel libcap-devel lame-devel libbluray-devel libnfs-devel ffmpeg-devel + taglib-devel libcap-devel lame-devel libbluray-devel libnfs-devel ffmpeg4-devel giflib-devel libxslt-devel gnutls-devel libssh-devel libmicrohttpd-devel libcec-devel dcadec-devel flatbuffers-devel fmt-devel lcms2-devel libfstrcmp-devel rapidjson libcdio-paranoia spdlog libwaylandpp-devel From d832cdd6cfe80c8f42987e971083cfc6542e4a8e Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:48 -0400 Subject: [PATCH 047/113] kpipewire: revbump for ffmpeg-6.0 --- srcpkgs/kpipewire/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/kpipewire/template b/srcpkgs/kpipewire/template index db4e42f0d456..2334bf867806 100644 --- a/srcpkgs/kpipewire/template +++ b/srcpkgs/kpipewire/template @@ -1,7 +1,7 @@ # Template file for 'kpipewire' pkgname=kpipewire version=5.27.6 -revision=1 +revision=2 build_style=cmake hostmakedepends="extra-cmake-modules plasma-wayland-protocols gettext qt5-qmake qt5-host-tools pkg-config wayland-devel kcoreaddons From ab4875f3ded74f497d8c492553bcb394acf8230b Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:48 -0400 Subject: [PATCH 048/113] libextractor: revbump for ffmpeg4-4.4.3 --- srcpkgs/libextractor/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/libextractor/template b/srcpkgs/libextractor/template index ddd4790f93e8..1fb9ca56a96a 100644 --- a/srcpkgs/libextractor/template +++ b/srcpkgs/libextractor/template @@ -7,7 +7,7 @@ configure_args="--disable-static" hostmakedepends="pkg-config" makedepends="zlib-devel bzip2-devel exiv2-devel tiff-devel libpng-devel libjpeg-turbo-devel libvorbis-devel libflac-devel giflib-devel libmpeg2-devel - ffmpeg-devel gtk+3-devel libltdl-devel libarchive-devel file-devel libgsf-devel" + ffmpeg4-devel gtk+3-devel libltdl-devel libarchive-devel file-devel libgsf-devel" short_desc="Library used to extract meta data from files" maintainer="Martin Riese " license="GPL-3.0-or-later" From e7b00c31422b57759e8525d97f80385aabfa2438 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:48 -0400 Subject: [PATCH 049/113] libopenal: revbump for ffmpeg-6.0 --- srcpkgs/libopenal/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/libopenal/template b/srcpkgs/libopenal/template index 77218f9e539d..3f49ed75a1fd 100644 --- a/srcpkgs/libopenal/template +++ b/srcpkgs/libopenal/template @@ -1,7 +1,7 @@ # Template file for 'libopenal' pkgname=libopenal version=1.22.2 -revision=1 +revision=2 build_style=cmake configure_args="-DALSOFT_EXAMPLES=OFF" hostmakedepends="pkg-config" From b5f31fba93e19c31a0c9640a8a848826cdf4ac52 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:48 -0400 Subject: [PATCH 050/113] libopenshot: revbump for ffmpeg-6.0 --- srcpkgs/libopenshot/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/libopenshot/template b/srcpkgs/libopenshot/template index db831f69b474..81aa0d7136d9 100644 --- a/srcpkgs/libopenshot/template +++ b/srcpkgs/libopenshot/template @@ -1,7 +1,7 @@ # Template file for 'libopenshot' pkgname=libopenshot version=0.3.0 -revision=1 +revision=2 build_style=cmake # Builds fail with Ruby-2.4.1 configure_args="-DENABLE_RUBY=OFF -DUSE_SYSTEM_JSONCPP=ON" From bd8ae4ebbff59acc6c76f1172a474fda776f133a Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:48 -0400 Subject: [PATCH 051/113] loudgain: revbump for ffmpeg-6.0 --- srcpkgs/loudgain/patches/ffmpeg5.patch | 11 +++++++++++ srcpkgs/loudgain/template | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 srcpkgs/loudgain/patches/ffmpeg5.patch diff --git a/srcpkgs/loudgain/patches/ffmpeg5.patch b/srcpkgs/loudgain/patches/ffmpeg5.patch new file mode 100644 index 000000000000..16d4510ee98f --- /dev/null +++ b/srcpkgs/loudgain/patches/ffmpeg5.patch @@ -0,0 +1,11 @@ +--- a/src/scan.c 2019-09-06 11:31:19.000000000 -0400 ++++ b/src/scan.c 2023-03-23 11:15:40.867968521 -0400 +@@ -69,8 +69,6 @@ + * It is now useless + * https://github.com/FFmpeg/FFmpeg/blob/70d25268c21cbee5f08304da95be1f647c630c15/doc/APIchanges#L86 + */ +- if (avformat_version() < AV_VERSION_INT(58,9,100)) +- av_register_all(); + + av_log_set_callback(scan_av_log); + diff --git a/srcpkgs/loudgain/template b/srcpkgs/loudgain/template index da4f2d56e94c..4d6bf29efb4f 100644 --- a/srcpkgs/loudgain/template +++ b/srcpkgs/loudgain/template @@ -1,7 +1,7 @@ # Template file for 'loudgain' pkgname=loudgain version=0.6.8 -revision=2 +revision=3 build_style=cmake hostmakedepends="pkg-config" makedepends="libebur128-devel taglib-devel ffmpeg-devel" From 8092a3ab783ff6903af23fc4405a70ca56d8e959 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:48 -0400 Subject: [PATCH 052/113] mediastreamer: revbump for ffmpeg4-4.4.3 --- srcpkgs/mediastreamer/template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srcpkgs/mediastreamer/template b/srcpkgs/mediastreamer/template index d0e97e858e29..1bde031443a5 100644 --- a/srcpkgs/mediastreamer/template +++ b/srcpkgs/mediastreamer/template @@ -1,11 +1,11 @@ # Template file for 'mediastreamer' pkgname=mediastreamer version=5.2.6 -revision=1 +revision=2 build_style=cmake configure_args="-DENABLE_STRICT=0 -DENABLE_UNIT_TESTS=0" hostmakedepends="python3" -makedepends="bzrtp-devel ffmpeg-devel glew-devel libXv-devel libsrtp-devel +makedepends="bzrtp-devel ffmpeg4-devel glew-devel libXv-devel libsrtp-devel libupnp-devel libvpx-devel mbedtls-devel opus-devel ortp-devel pulseaudio-devel libtheora-devel speex-devel v4l-utils-devel bcg729-devel bcmatroska2-devel libgsm-devel" # zxing-cpp-devel (1.2.0 probably not compatible, check again after updaing xzing) From d217057287f5589ab99707523c9ee4a1f2072be5 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:48 -0400 Subject: [PATCH 053/113] mgba: revbump for ffmpeg-6.0 --- srcpkgs/mgba/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/mgba/template b/srcpkgs/mgba/template index ae0504311eee..d31295a0cd3d 100644 --- a/srcpkgs/mgba/template +++ b/srcpkgs/mgba/template @@ -1,7 +1,7 @@ # Template file for 'mgba' pkgname=mgba version=0.10.2 -revision=1 +revision=2 build_style=cmake hostmakedepends="pkg-config qt5-host-tools qt5-qmake desktop-file-utils" makedepends="SDL2-devel ffmpeg-devel libedit-devel libepoxy-devel libmagick-devel From c1249f47c21e7098559b780a321aaba3ce976c4a Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:48 -0400 Subject: [PATCH 054/113] minidlna: revbump for ffmpeg-6.0 --- srcpkgs/minidlna/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/minidlna/template b/srcpkgs/minidlna/template index d551e49ed465..5fa929f3a0c1 100644 --- a/srcpkgs/minidlna/template +++ b/srcpkgs/minidlna/template @@ -1,7 +1,7 @@ # Template file for 'minidlna' pkgname=minidlna version=1.3.3 -revision=1 +revision=2 build_style=gnu-configure configure_args=" --sbindir=/usr/bin From 4ae4ddf71a2e14290d920e0a12d24e0802e601d2 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:49 -0400 Subject: [PATCH 055/113] mixxx: revbump for ffmpeg-6.0 --- srcpkgs/mixxx/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/mixxx/template b/srcpkgs/mixxx/template index 619ddca0d332..4b9ea00d3fb3 100644 --- a/srcpkgs/mixxx/template +++ b/srcpkgs/mixxx/template @@ -1,7 +1,7 @@ # Template file for 'mixxx' pkgname=mixxx version=2.3.3 -revision=1 +revision=2 build_style=cmake configure_args="-DCMAKE_BUILD_TYPE=Release" hostmakedepends="extra-cmake-modules pkg-config protobuf qt5-host-tools qt5-devel" From a46e80408b5958bd3114b3412c985dfcc2fe0f38 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:49 -0400 Subject: [PATCH 056/113] mlt: revbump for ffmpeg4-4.4.3 --- srcpkgs/mlt/template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srcpkgs/mlt/template b/srcpkgs/mlt/template index 8933eb4e7bb9..73353fedafb5 100644 --- a/srcpkgs/mlt/template +++ b/srcpkgs/mlt/template @@ -1,14 +1,14 @@ # Template file for 'mlt' pkgname=mlt version=6.26.1 -revision=1 +revision=2 build_style=configure configure_args="--prefix=/usr --libdir=/usr/lib$XBPS_TARGET_WORDSIZE --enable-gpl --enable-gpl3 --disable-swfdec --without-kde --swig-languages=python" hostmakedepends="doxygen pkg-config ladspa-sdk swig python3 which" # XXX: movit vid.stab -makedepends="alsa-lib-devel ffmpeg-devel gtk+-devel jack-devel ladspa-sdk +makedepends="alsa-lib-devel ffmpeg4-devel gtk+-devel jack-devel ladspa-sdk libexif-devel libsamplerate-devel libxml2-devel sox-devel SDL_image-devel fftw-devel frei0r-plugins python3-devel pulseaudio-devel movit-devel libvidstab-devel libatomic-devel" From 14b9c837e49a8106a232cf3462e0d652fe4f4a03 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:49 -0400 Subject: [PATCH 057/113] moc: revbump for ffmpeg4-4.4.3 --- srcpkgs/moc/template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srcpkgs/moc/template b/srcpkgs/moc/template index c42be650a1d2..d4f0eefbad52 100644 --- a/srcpkgs/moc/template +++ b/srcpkgs/moc/template @@ -1,10 +1,10 @@ # Template file for 'moc' pkgname=moc version=2.5.2 -revision=6 +revision=7 build_style=gnu-configure hostmakedepends="pkg-config" -makedepends="db-devel ncurses-devel libcurl-devel popt-devel ffmpeg-devel +makedepends="db-devel ncurses-devel libcurl-devel popt-devel ffmpeg4-devel jack-devel alsa-lib-devel libltdl-devel libflac-devel libvorbis-devel libmad-devel libmpcdec-devel libmodplug-devel libid3tag-devel faad2-devel taglib-devel libsndfile-devel wavpack-devel speex-devel libsamplerate-devel From 813362ec0cc7059941f0967dffdf032ecb9a6cfb Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:49 -0400 Subject: [PATCH 058/113] motion: revbump for ffmpeg-6.0 --- srcpkgs/motion/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/motion/template b/srcpkgs/motion/template index 3cf3c3035c5b..7dca12d851e3 100644 --- a/srcpkgs/motion/template +++ b/srcpkgs/motion/template @@ -1,7 +1,7 @@ # Template file for 'motion' pkgname=motion version=4.5.1 -revision=1 +revision=2 build_style=gnu-configure hostmakedepends="automake pkg-config gettext-devel tar" makedepends="ffmpeg-devel libmicrohttpd-devel v4l-utils-devel gettext-devel" From 1fd359b67bf608bc80cdd057aba032642a72e1d9 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:49 -0400 Subject: [PATCH 059/113] mpv: revbump for ffmpeg-6.0 --- srcpkgs/mpv/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/mpv/template b/srcpkgs/mpv/template index e163c496c6eb..d4fefbf5e3c7 100644 --- a/srcpkgs/mpv/template +++ b/srcpkgs/mpv/template @@ -1,7 +1,7 @@ # Template file for 'mpv' pkgname=mpv version=0.35.1 -revision=2 +revision=3 build_style=meson configure_args="-Dcdda=enabled -Ddvbin=enabled -Ddvdnav=enabled -Dlibmpv=true -Dcplugins=enabled From c8c593da81ceff294860fcfcb47e5f1653c156d1 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:49 -0400 Subject: [PATCH 060/113] musikcube: revbump for ffmpeg-6.0 --- srcpkgs/musikcube/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/musikcube/template b/srcpkgs/musikcube/template index 7c569303c054..a4dea460c371 100644 --- a/srcpkgs/musikcube/template +++ b/srcpkgs/musikcube/template @@ -1,7 +1,7 @@ # Template file for 'musikcube' pkgname=musikcube version=3.0.0 -revision=1 +revision=2 build_style=cmake make_cmd=make configure_args="-DNO_NCURSESW=1" From 369943f0f44af7e348d4eba2b7f4fbab8e39529d Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:49 -0400 Subject: [PATCH 061/113] notcurses: revbump for ffmpeg-6.0 --- srcpkgs/notcurses/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/notcurses/template b/srcpkgs/notcurses/template index 6dd8a091319f..3110c30c9aff 100644 --- a/srcpkgs/notcurses/template +++ b/srcpkgs/notcurses/template @@ -1,7 +1,7 @@ # Template file for 'notcurses' pkgname=notcurses version=3.0.9 -revision=1 +revision=2 build_style=cmake configure_args="-DUSE_STATIC=ON $(vopt_bool man USE_PANDOC)" hostmakedepends="pkg-config $(vopt_if man pandoc)" From 8a30cf9e6a843e1f00ff7c9afc860496b1c7fa18 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:49 -0400 Subject: [PATCH 062/113] obs: revbump for ffmpeg-6.0 --- srcpkgs/obs/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/obs/template b/srcpkgs/obs/template index 7b69c630d30d..2c8d68d71f3a 100644 --- a/srcpkgs/obs/template +++ b/srcpkgs/obs/template @@ -1,7 +1,7 @@ # Template file for 'obs' pkgname=obs version=29.1.2 -revision=1 +revision=2 archs="i686* x86_64* ppc64le* aarch64*" build_style=cmake configure_args="-DOBS_VERSION_OVERRIDE=${version} -DENABLE_JACK=ON From 7d4540259e2d72a59f514497f5b6e0d3003b4fed Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:49 -0400 Subject: [PATCH 063/113] olive: revbump for ffmpeg4-4.4.3 --- srcpkgs/olive/template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srcpkgs/olive/template b/srcpkgs/olive/template index 12a46936c990..5c2917b9c512 100644 --- a/srcpkgs/olive/template +++ b/srcpkgs/olive/template @@ -1,10 +1,10 @@ # Template file for 'olive' pkgname=olive version=0.1.2 -revision=2 +revision=3 build_style=qmake hostmakedepends="qt5-qmake qt5-host-tools pkg-config" -makedepends="qt5-devel qt5-multimedia-devel qt5-svg-devel ffmpeg-devel frei0r-plugins" +makedepends="qt5-devel qt5-multimedia-devel qt5-svg-devel ffmpeg4-devel frei0r-plugins" short_desc="Non-linear video editor" maintainer="Orphaned " license="GPL-3.0-or-later" From 508ffbec2043a331c00669816c83074f62dd4e5c Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:49 -0400 Subject: [PATCH 064/113] omxplayer: revbump for ffmpeg4-4.4.3 --- srcpkgs/omxplayer/template | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/srcpkgs/omxplayer/template b/srcpkgs/omxplayer/template index e70bf7873d4d..0e9bc70e7c8e 100644 --- a/srcpkgs/omxplayer/template +++ b/srcpkgs/omxplayer/template @@ -1,10 +1,10 @@ # Template file for 'omxplayer' pkgname=omxplayer version=20190102 -revision=1 +revision=2 short_desc="Commandline OMX player for the Raspberry Pi" maintainer="Orphaned " -license="GPL-2" +license="GPL-2.0-or-later" homepage="https://github.com/popcornmix/omxplayer" _commit="f06235cc9690a6d58187514452df8cf8fcdaacec" @@ -15,7 +15,7 @@ checksum=af2d9450f8947842ea8c401fe9f71eec444013ebbdee29f2ac828c9c493c1329 archs="armv6l* armv7l*" build_style=gnu-makefile hostmakedepends="curl pkg-config" -makedepends="alsa-lib-devel rpi-userland-devel pcre-devel boost-devel freetype-devel ffmpeg-devel dbus-devel" +makedepends="alsa-lib-devel rpi-userland-devel pcre-devel boost-devel freetype-devel ffmpeg4-devel dbus-devel" depends="freefont-ttf" do_build() { From 2cce0a838368ef79ae5e9e616cb8f444c790b9b8 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:50 -0400 Subject: [PATCH 065/113] openshot: revbump for ffmpeg-6.0 --- srcpkgs/openshot/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/openshot/template b/srcpkgs/openshot/template index 322717d40abc..c074e0338773 100644 --- a/srcpkgs/openshot/template +++ b/srcpkgs/openshot/template @@ -1,7 +1,7 @@ # Template file for 'openshot' pkgname=openshot version=3.0.0 -revision=1 +revision=2 build_style=python3-module hostmakedepends="python3 python3-setuptools" makedepends="ffmpeg-devel python3-PyQt5" From 53888d63a35cc86a22ceca310d9a8c1f0e66efa9 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:50 -0400 Subject: [PATCH 066/113] opentoonz: revbump for ffmpeg-6.0 --- srcpkgs/opentoonz/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/opentoonz/template b/srcpkgs/opentoonz/template index ee9f7603f55f..3e81834ca0ed 100644 --- a/srcpkgs/opentoonz/template +++ b/srcpkgs/opentoonz/template @@ -1,7 +1,7 @@ # Template file for 'opentoonz' pkgname=opentoonz version=1.6.0 -revision=2 +revision=3 build_wrksrc="toonz/sources" build_style=cmake make_cmd=make From caf0d5eaf05a31c767cd67ed682f9c131e6c7766 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:50 -0400 Subject: [PATCH 067/113] pianobar: revbump for ffmpeg-6.0 --- srcpkgs/pianobar/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/pianobar/template b/srcpkgs/pianobar/template index e3febb821a45..1e3dc1bf9308 100644 --- a/srcpkgs/pianobar/template +++ b/srcpkgs/pianobar/template @@ -1,7 +1,7 @@ # Template file for 'pianobar' pkgname=pianobar version=2022.04.01 -revision=1 +revision=2 build_style=gnu-makefile make_build_args="V=1" hostmakedepends="pkg-config" From 3eeb517ecf23a25f11e8d1deebaf5088afc6ef58 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:50 -0400 Subject: [PATCH 068/113] ppsspp: revbump for ffmpeg4-4.4.3 --- srcpkgs/ppsspp/template | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/srcpkgs/ppsspp/template b/srcpkgs/ppsspp/template index 7984a733d4be..15a42fd2c993 100644 --- a/srcpkgs/ppsspp/template +++ b/srcpkgs/ppsspp/template @@ -1,7 +1,7 @@ # Template file for 'ppsspp' pkgname=ppsspp version=1.14.4 -revision=1 +revision=2 _glslang_commit=dc11adde23c455a24e13dd54de9b4ede8bdd7db8 _SPIRV_Cross_commit=9acb9ec31f5a8ef80ea6b994bb77be787b08d3d1 _armips_commit=6719edebaae03330ee5441d9b28280672edf00d5 @@ -13,7 +13,7 @@ configure_args="-DHEADLESS=1 -DUSE_SYSTEM_FFMPEG=1 -DUNITTEST=ON -DUSING_QT_UI=$(vopt_if qt ON OFF) -DUSE_SYSTEM_ZSTD=ON -DARMIPS_USE_STD_FILESYSTEM=ON" hostmakedepends="pkg-config python3 $(vopt_if qt qt5-host-tools)" -makedepends="zlib-devel glew-devel ffmpeg-devel libzip-devel +makedepends="zlib-devel glew-devel ffmpeg4-devel libzip-devel snappy-devel rapidjson libpng-devel libzstd-devel $(vopt_if sdl2 SDL2-devel) $(vopt_if wayland wayland-devel) $(vopt_if qt 'qt5-devel qt5-multimedia-devel')" @@ -62,13 +62,12 @@ post_extract() { mv ${wrksrc}/miniupnp-${_miniupnp_commit} ${wrksrc}/ext/miniupnp } -post_patch(){ +post_patch() { # disable git versioning vsed -e 's|find_package(Git)|# &|' -i git-version.cmake } do_install() { - vlicense LICENSE.TXT vinstall icons/icon.svg 644 usr/share/pixmaps ppsspp.svg vinstall Qt/PPSSPP.desktop 644 usr/share/applications vbin build/PPSSPPHeadless ppsspp-headless From 0597f6e814a70cf830e05a0c50be208ec8964e9d Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:50 -0400 Subject: [PATCH 069/113] pqiv: revbump for ffmpeg-6.0 --- srcpkgs/pqiv/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/pqiv/template b/srcpkgs/pqiv/template index 542fc27a2d32..9308d949b6a1 100644 --- a/srcpkgs/pqiv/template +++ b/srcpkgs/pqiv/template @@ -1,7 +1,7 @@ # Template file for 'pqiv' pkgname=pqiv version=2.12 -revision=1 +revision=2 build_style=gnu-makefile hostmakedepends="pkg-config" makedepends="glib-devel gtk+3-devel $(vopt_if ffmpeg ffmpeg-devel) From c32df46cae8c8888e4782b9a471c7d265924df0b Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:50 -0400 Subject: [PATCH 070/113] qmmp: revbump for ffmpeg-6.0 --- srcpkgs/qmmp/template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpkgs/qmmp/template b/srcpkgs/qmmp/template index 26c661ed16be..a150d7441c7a 100644 --- a/srcpkgs/qmmp/template +++ b/srcpkgs/qmmp/template @@ -1,7 +1,7 @@ # Template file for 'qmmp' pkgname=qmmp version=1.6.1 -revision=1 +revision=2 build_style=cmake configure_args="-DUSE_HAL:BOOL=FALSE -DQMMP_DEFAULT_UI:STRING=simple" hostmakedepends="pkg-config qt5-host-tools qt5-qmake" From 82afd18905aeb81acd211651af3c374574f92550 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:50 -0400 Subject: [PATCH 071/113] qt5-webengine: update to 5.15.13 --- .../chromium-media-filters-cpp14.patch | 11 ++ srcpkgs/qt5-webengine/patches/ffmpeg5.patch | 179 ++++++++++++++++++ srcpkgs/qt5-webengine/template | 10 +- 3 files changed, 195 insertions(+), 5 deletions(-) create mode 100644 srcpkgs/qt5-webengine/patches/chromium-media-filters-cpp14.patch create mode 100644 srcpkgs/qt5-webengine/patches/ffmpeg5.patch diff --git a/srcpkgs/qt5-webengine/patches/chromium-media-filters-cpp14.patch b/srcpkgs/qt5-webengine/patches/chromium-media-filters-cpp14.patch new file mode 100644 index 000000000000..04adc540f2cb --- /dev/null +++ b/srcpkgs/qt5-webengine/patches/chromium-media-filters-cpp14.patch @@ -0,0 +1,11 @@ +--- a/src/3rdparty/chromium/media/filters/BUILD.gn 2023-02-27 13:32:59.000000000 -0500 ++++ b/src/3rdparty/chromium/media/filters/BUILD.gn 2023-04-02 17:21:39.204066384 -0400 +@@ -96,6 +96,8 @@ + "//ui/gfx/geometry:geometry", + ] + ++ cflags_cc = [ "-std=c++14" ] ++ + libs = [] + + if (proprietary_codecs) { diff --git a/srcpkgs/qt5-webengine/patches/ffmpeg5.patch b/srcpkgs/qt5-webengine/patches/ffmpeg5.patch new file mode 100644 index 000000000000..ac55e1634423 --- /dev/null +++ b/srcpkgs/qt5-webengine/patches/ffmpeg5.patch @@ -0,0 +1,179 @@ +--- a/src/3rdparty/chromium/media/filters/ffmpeg_demuxer.cc 2023-04-02 16:50:57.732547446 -0400 ++++ b/src/3rdparty/chromium/media/filters/ffmpeg_demuxer.cc 2023-04-02 16:50:09.486478995 -0400 +@@ -57,6 +57,8 @@ + + namespace { + ++constexpr int64_t kRelativeTsBase = static_cast(0x7ffeffffffffffff); ++ + void SetAVStreamDiscard(AVStream* stream, AVDiscard discard) { + DCHECK(stream); + stream->discard = discard; +@@ -90,24 +92,12 @@ + + static base::TimeDelta ExtractStartTime(AVStream* stream) { + // The default start time is zero. +- base::TimeDelta start_time; ++ base::TimeDelta start_time = kNoTimestamp; + + // First try to use the |start_time| value as is. + if (stream->start_time != kNoFFmpegTimestamp) + start_time = ConvertFromTimeBase(stream->time_base, stream->start_time); + +- // Next try to use the first DTS value, for codecs where we know PTS == DTS +- // (excludes all H26x codecs). The start time must be returned in PTS. +- if (stream->first_dts != kNoFFmpegTimestamp && +- stream->codecpar->codec_id != AV_CODEC_ID_HEVC && +- stream->codecpar->codec_id != AV_CODEC_ID_H264 && +- stream->codecpar->codec_id != AV_CODEC_ID_MPEG4) { +- const base::TimeDelta first_pts = +- ConvertFromTimeBase(stream->time_base, stream->first_dts); +- if (first_pts < start_time) +- start_time = first_pts; +- } +- + return start_time; + } + +@@ -408,11 +398,11 @@ + scoped_refptr buffer; + + if (type() == DemuxerStream::TEXT) { +- int id_size = 0; ++ size_t id_size = 0; + uint8_t* id_data = av_packet_get_side_data( + packet.get(), AV_PKT_DATA_WEBVTT_IDENTIFIER, &id_size); + +- int settings_size = 0; ++ size_t settings_size = 0; + uint8_t* settings_data = av_packet_get_side_data( + packet.get(), AV_PKT_DATA_WEBVTT_SETTINGS, &settings_size); + +@@ -424,7 +414,7 @@ + buffer = DecoderBuffer::CopyFrom(packet->data, packet->size, + side_data.data(), side_data.size()); + } else { +- int side_data_size = 0; ++ size_t side_data_size = 0; + uint8_t* side_data = av_packet_get_side_data( + packet.get(), AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, &side_data_size); + +@@ -485,7 +475,7 @@ + packet->size - data_offset); + } + +- int skip_samples_size = 0; ++ size_t skip_samples_size = 0; + const uint32_t* skip_samples_ptr = + reinterpret_cast(av_packet_get_side_data( + packet.get(), AV_PKT_DATA_SKIP_SAMPLES, &skip_samples_size)); +@@ -1587,6 +1577,8 @@ + for (const auto& stream : streams_) { + if (!stream || stream->IsEnabled() != enabled) + continue; ++ if (stream->av_stream()->start_time == AV_NOPTS_VALUE) ++ continue; + if (!lowest_start_time_stream || + stream->start_time() < lowest_start_time_stream->start_time()) { + lowest_start_time_stream = stream.get(); +@@ -1604,6 +1596,8 @@ + if (stream && stream->type() == DemuxerStream::VIDEO && + stream->IsEnabled()) { + video_stream = stream.get(); ++ if (stream->av_stream()->start_time == AV_NOPTS_VALUE) ++ continue; + if (video_stream->start_time() <= seek_time) { + return video_stream; + } +diff -Naurp qtwebengine-5.15.10.orig/src/3rdparty/chromium/media/ffmpeg/ffmpeg_common.h qtwebengine-5.15.10/src/3rdparty/chromium/media/ffmpeg/ffmpeg_common.h +--- a/src/3rdparty/chromium/media/ffmpeg/ffmpeg_common.h 2022-05-23 06:38:40.000000000 -0500 ++++ b/src/3rdparty/chromium/media/ffmpeg/ffmpeg_common.h 2022-07-11 22:12:47.917192788 -0500 +@@ -29,6 +29,7 @@ extern "C" { + #include + #include + #include ++#include + #include + #include + #include +diff -Naurp qtwebengine-5.15.10.orig/src/3rdparty/chromium/media/filters/audio_file_reader.cc qtwebengine-5.15.10/src/3rdparty/chromium/media/filters/audio_file_reader.cc +--- a/src/3rdparty/chromium/media/filters/audio_file_reader.cc 2022-05-23 06:38:40.000000000 -0500 ++++ b/src/3rdparty/chromium/media/filters/audio_file_reader.cc 2022-07-11 22:12:47.917192788 -0500 +@@ -85,7 +85,7 @@ bool AudioFileReader::OpenDemuxer() { + } + + bool AudioFileReader::OpenDecoder() { +- AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); ++ const AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); + if (codec) { + // MP3 decodes to S16P which we don't support, tell it to use S16 instead. + if (codec_context_->sample_fmt == AV_SAMPLE_FMT_S16P) +diff -Naurp qtwebengine-5.15.10.orig/src/3rdparty/chromium/media/filters/ffmpeg_audio_decoder.cc qtwebengine-5.15.10/src/3rdparty/chromium/media/filters/ffmpeg_audio_decoder.cc +--- a/src/3rdparty/chromium/media/filters/ffmpeg_audio_decoder.cc 2022-05-23 06:38:40.000000000 -0500 ++++ b/src/3rdparty/chromium/media/filters/ffmpeg_audio_decoder.cc 2022-07-11 22:12:47.917192788 -0500 +@@ -329,7 +329,7 @@ bool FFmpegAudioDecoder::ConfigureDecode + } + } + +- AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); ++ const AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); + if (!codec || + avcodec_open2(codec_context_.get(), codec, &codec_options) < 0) { + DLOG(ERROR) << "Could not initialize audio decoder: " +diff -Naurp qtwebengine-5.15.10.orig/src/3rdparty/chromium/media/filters/ffmpeg_glue.cc qtwebengine-5.15.10/src/3rdparty/chromium/media/filters/ffmpeg_glue.cc +--- a/src/3rdparty/chromium/media/filters/ffmpeg_glue.cc 2022-05-23 06:38:40.000000000 -0500 ++++ b/src/3rdparty/chromium/media/filters/ffmpeg_glue.cc 2022-07-11 22:12:47.918192779 -0500 +@@ -59,7 +59,6 @@ static int64_t AVIOSeekOperation(void* o + } + + void FFmpegGlue::InitializeFFmpeg() { +- av_register_all(); + } + + static void LogContainer(bool is_local_file, +@@ -95,9 +94,6 @@ FFmpegGlue::FFmpegGlue(FFmpegURLProtocol + // Enable fast, but inaccurate seeks for MP3. + format_context_->flags |= AVFMT_FLAG_FAST_SEEK; + +- // Ensures we can read out various metadata bits like vp8 alpha. +- format_context_->flags |= AVFMT_FLAG_KEEP_SIDE_DATA; +- + // Ensures format parsing errors will bail out. From an audit on 11/2017, all + // instances were real failures. Solves bugs like http://crbug.com/710791. + format_context_->error_recognition |= AV_EF_EXPLODE; +diff -Naurp qtwebengine-5.15.10.orig/src/3rdparty/chromium/media/filters/ffmpeg_video_decoder.cc qtwebengine-5.15.10/src/3rdparty/chromium/media/filters/ffmpeg_video_decoder.cc +--- a/src/3rdparty/chromium/media/filters/ffmpeg_video_decoder.cc 2022-05-23 06:38:40.000000000 -0500 ++++ b/src/3rdparty/chromium/media/filters/ffmpeg_video_decoder.cc 2022-07-11 22:12:47.918192779 -0500 +@@ -391,7 +391,7 @@ bool FFmpegVideoDecoder::ConfigureDecode + if (decode_nalus_) + codec_context_->flags2 |= AV_CODEC_FLAG2_CHUNKS; + +- AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); ++ const AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); + if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) { + ReleaseFFmpegResources(); + return false; +diff -Naurp qtwebengine-5.15.10.orig/src/3rdparty/chromium/media/filters/media_file_checker.cc qtwebengine-5.15.10/src/3rdparty/chromium/media/filters/media_file_checker.cc +--- a/src/3rdparty/chromium/media/filters/media_file_checker.cc 2022-05-23 06:38:40.000000000 -0500 ++++ b/src/3rdparty/chromium/media/filters/media_file_checker.cc 2022-07-11 22:12:47.918192779 -0500 +@@ -68,7 +68,7 @@ bool MediaFileChecker::Start(base::TimeD + auto context = AVStreamToAVCodecContext(format_context->streams[i]); + if (!context) + continue; +- AVCodec* codec = avcodec_find_decoder(cp->codec_id); ++ const AVCodec* codec = avcodec_find_decoder(cp->codec_id); + if (codec && avcodec_open2(context.get(), codec, nullptr) >= 0) { + auto loop = std::make_unique(context.get()); + stream_contexts[i] = {std::move(context), std::move(loop)}; +diff -Naurp qtwebengine-5.15.10.orig/src/3rdparty/chromium/third_party/webrtc/modules/video_coding/codecs/h264/h264_decoder_impl.cc qtwebengine-5.15.10/src/3rdparty/chromium/third_party/webrtc/modules/video_coding/codecs/h264/h264_decoder_impl.cc +--- a/src/3rdparty/chromium/third_party/webrtc/modules/video_coding/codecs/h264/h264_decoder_impl.cc 2022-05-23 06:38:40.000000000 -0500 ++++ b/src/3rdparty/chromium/third_party/webrtc/modules/video_coding/codecs/h264/h264_decoder_impl.cc 2022-07-11 22:12:47.918192779 -0500 +@@ -203,7 +203,7 @@ int32_t H264DecoderImpl::InitDecode(cons + // a pointer |this|. + av_context_->opaque = this; + +- AVCodec* codec = avcodec_find_decoder(av_context_->codec_id); ++ const AVCodec* codec = avcodec_find_decoder(av_context_->codec_id); + if (!codec) { + // This is an indication that FFmpeg has not been initialized or it has not + // been compiled/initialized with the correct set of codecs. diff --git a/srcpkgs/qt5-webengine/template b/srcpkgs/qt5-webengine/template index 85267c7cf8a3..095ab67701e4 100644 --- a/srcpkgs/qt5-webengine/template +++ b/srcpkgs/qt5-webengine/template @@ -1,9 +1,9 @@ # Template file for 'qt5-webengine' pkgname=qt5-webengine -version=5.15.11 -revision=3 +version=5.15.13 +revision=1 _version="${version}-lts" -_chromium_commit=be349eaf62e77955791d7bf29f893f1e8a37daf4 +_chromium_commit=e48df7803c7c98b0b2471c94057d32e44a301ad5 archs="x86_64* i686* armv[67]* ppc64* aarch64*" create_wrksrc=yes build_style=qmake @@ -32,8 +32,8 @@ license="GPL-3.0-or-later, LGPL-3.0-or-later" homepage="https://qt.io/" distfiles="https://github.com/qt/qtwebengine/archive/v${_version}.tar.gz https://github.com/qt/qtwebengine-chromium/archive/${_chromium_commit}.tar.gz" -checksum="aa7466356c450c5f5870f979b93cd7e7e62da1165c328ffcab1a9928db18ad67 - 6f47ed8ab8cc062411f6f206da6353bc8263d6ed6d6290c689a05c01d91f646b" +checksum="4b59838ed75ef788b59e1e412535a0e42dd9d311661fdeadb191b581ba815c63 + a91686562b1d4e8b220e0bbcbab5feb64630e2de974b35ac034bf388af771a6c" no_generic_pkgconfig_link=yes build_options="sndio pipewire" From da23d8ab80a6fa1b1d619f4e618a3b842f998c84 Mon Sep 17 00:00:00 2001 From: zlice Date: Wed, 22 Mar 2023 20:01:51 -0400 Subject: [PATCH 072/113] qt5: update to 5.15.8 --- ...erywhere-opensource-src-5.15.8-kf5-1.patch | 12913 ++++++++++++++++ srcpkgs/qt5/template | 12 +- 2 files changed, 12919 insertions(+), 6 deletions(-) create mode 100644 srcpkgs/qt5/patches/qt-everywhere-opensource-src-5.15.8-kf5-1.patch diff --git a/srcpkgs/qt5/patches/qt-everywhere-opensource-src-5.15.8-kf5-1.patch b/srcpkgs/qt5/patches/qt-everywhere-opensource-src-5.15.8-kf5-1.patch new file mode 100644 index 000000000000..966c98bcd3bb --- /dev/null +++ b/srcpkgs/qt5/patches/qt-everywhere-opensource-src-5.15.8-kf5-1.patch @@ -0,0 +1,12913 @@ +Submitted By: Pierre Labastie +Date: 2023-01-05 +Initial Package Version: 5.15.8 +Upstream Status: Applied (according to KDE) +Origin: KDE patch set +Description: Patch set maintained by the KDE folks +see https://dot.kde.org/2021/04/06/announcing-kdes-qt-5-patch-collection +Patch generated using the procedure in +https://wiki.linuxfromscratch.org/blfs/ticket/17476#comment:3 + +Submodule qtbase 4ee4fc18..9cf586d6: +diff --git a/qtbase/mkspecs/common/android/qplatformdefs.h b/qtbase/mkspecs/common/android/qplatformdefs.h +index f75bc4093b..2bd59410d4 100644 +--- a/qtbase/mkspecs/common/android/qplatformdefs.h ++++ b/qtbase/mkspecs/common/android/qplatformdefs.h +@@ -144,11 +144,7 @@ + #define QT_SIGNAL_ARGS int + #define QT_SIGNAL_IGNORE SIG_IGN + +-#if defined(__GLIBC__) && (__GLIBC__ >= 2) + #define QT_SOCKLEN_T socklen_t +-#else +-#define QT_SOCKLEN_T int +-#endif + + #if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500) + #define QT_SNPRINTF ::snprintf +diff --git a/qtbase/mkspecs/features/mac/sdk.mk b/qtbase/mkspecs/features/mac/sdk.mk +index f30b5830b4..a32ceacb6c 100644 +--- a/qtbase/mkspecs/features/mac/sdk.mk ++++ b/qtbase/mkspecs/features/mac/sdk.mk +@@ -1,6 +1,6 @@ + + ifeq ($(QT_MAC_SDK_NO_VERSION_CHECK),) +- CHECK_SDK_COMMAND = /usr/bin/xcrun --sdk $(EXPORT_QMAKE_MAC_SDK) -show-sdk-version 2>&1 ++ CHECK_SDK_COMMAND = /usr/bin/xcrun --sdk $(EXPORT_QMAKE_MAC_SDK) -show-sdk-version 2>/dev/null + CURRENT_MAC_SDK_VERSION := $(shell DEVELOPER_DIR=$(EXPORT_QMAKE_XCODE_DEVELOPER_PATH) $(CHECK_SDK_COMMAND)) + ifneq ($(CURRENT_MAC_SDK_VERSION),$(EXPORT_QMAKE_MAC_SDK_VERSION)) + # We don't want to complain about out of date SDK unless the target needs to be remade. +diff --git a/qtbase/mkspecs/linux-clang/qplatformdefs.h b/qtbase/mkspecs/linux-clang/qplatformdefs.h +index a818d973f0..c1ab72fbc6 100644 +--- a/qtbase/mkspecs/linux-clang/qplatformdefs.h ++++ b/qtbase/mkspecs/linux-clang/qplatformdefs.h +@@ -79,14 +79,6 @@ + #define QT_USE_XOPEN_LFS_EXTENSIONS + #include "../common/posix/qplatformdefs.h" + +-#undef QT_SOCKLEN_T +- +-#if defined(__GLIBC__) && (__GLIBC__ >= 2) +-#define QT_SOCKLEN_T socklen_t +-#else +-#define QT_SOCKLEN_T int +-#endif +- + #if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500) + #define QT_SNPRINTF ::snprintf + #define QT_VSNPRINTF ::vsnprintf +diff --git a/qtbase/mkspecs/linux-g++/qplatformdefs.h b/qtbase/mkspecs/linux-g++/qplatformdefs.h +index 13523f0702..4d2750d9ec 100644 +--- a/qtbase/mkspecs/linux-g++/qplatformdefs.h ++++ b/qtbase/mkspecs/linux-g++/qplatformdefs.h +@@ -79,14 +79,6 @@ + #define QT_USE_XOPEN_LFS_EXTENSIONS + #include "../common/posix/qplatformdefs.h" + +-#undef QT_SOCKLEN_T +- +-#if defined(__GLIBC__) && (__GLIBC__ < 2) +-#define QT_SOCKLEN_T int +-#else +-#define QT_SOCKLEN_T socklen_t +-#endif +- + #if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500) + #define QT_SNPRINTF ::snprintf + #define QT_VSNPRINTF ::vsnprintf +diff --git a/qtbase/mkspecs/linux-llvm/qplatformdefs.h b/qtbase/mkspecs/linux-llvm/qplatformdefs.h +index dc750ab1ef..d3cc39b47f 100644 +--- a/qtbase/mkspecs/linux-llvm/qplatformdefs.h ++++ b/qtbase/mkspecs/linux-llvm/qplatformdefs.h +@@ -80,14 +80,6 @@ + #define QT_USE_XOPEN_LFS_EXTENSIONS + #include "../common/posix/qplatformdefs.h" + +-#undef QT_SOCKLEN_T +- +-#if defined(__GLIBC__) && (__GLIBC__ >= 2) +-#define QT_SOCKLEN_T socklen_t +-#else +-#define QT_SOCKLEN_T int +-#endif +- + #if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500) + #define QT_SNPRINTF ::snprintf + #define QT_VSNPRINTF ::vsnprintf +diff --git a/qtbase/mkspecs/linux-lsb-g++/qplatformdefs.h b/qtbase/mkspecs/linux-lsb-g++/qplatformdefs.h +index 4c4e53da2a..83baffb3e3 100644 +--- a/qtbase/mkspecs/linux-lsb-g++/qplatformdefs.h ++++ b/qtbase/mkspecs/linux-lsb-g++/qplatformdefs.h +@@ -85,16 +85,9 @@ + #include "../common/posix/qplatformdefs.h" + + #undef QT_OPEN_LARGEFILE +-#undef QT_SOCKLEN_T + + #define QT_OPEN_LARGEFILE 0 + +-#if defined(__GLIBC__) && (__GLIBC__ >= 2) +-#define QT_SOCKLEN_T socklen_t +-#else +-#define QT_SOCKLEN_T int +-#endif +- + #ifndef SIOCGIFBRDADDR + # define SIOCGIFBRDADDR 0x8919 + #endif +diff --git a/qtbase/mkspecs/lynxos-g++/qplatformdefs.h b/qtbase/mkspecs/lynxos-g++/qplatformdefs.h +index 4339ea2b23..6007af0055 100644 +--- a/qtbase/mkspecs/lynxos-g++/qplatformdefs.h ++++ b/qtbase/mkspecs/lynxos-g++/qplatformdefs.h +@@ -72,14 +72,6 @@ + + #include "../common/posix/qplatformdefs.h" + +-#undef QT_SOCKLEN_T +- +-#if defined(__GLIBC__) && (__GLIBC__ >= 2) +-#define QT_SOCKLEN_T socklen_t +-#else +-#define QT_SOCKLEN_T int +-#endif +- + #if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500) + #define QT_SNPRINTF ::snprintf + #define QT_VSNPRINTF ::vsnprintf +diff --git a/qtbase/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp b/qtbase/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp +index c3c184258f..32af3f8f29 100644 +--- a/qtbase/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp ++++ b/qtbase/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp +@@ -10,6 +10,7 @@ + #include "libANGLE/HandleAllocator.h" + + #include ++#include + + #include "common/debug.h" + +diff --git a/qtbase/src/3rdparty/forkfd/forkfd_linux.c b/qtbase/src/3rdparty/forkfd/forkfd_linux.c +index ffe0e9a5e2..b1f5408d11 100644 +--- a/qtbase/src/3rdparty/forkfd/forkfd_linux.c ++++ b/qtbase/src/3rdparty/forkfd/forkfd_linux.c +@@ -82,7 +82,8 @@ static int sys_clone(unsigned long cloneflags, int *ptid) + return syscall(__NR_clone, cloneflags, child_stack, stack_size, ptid, newtls, ctid); + #elif defined(__arc__) || defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \ + defined(__nds32__) || defined(__hppa__) || defined(__powerpc__) || defined(__i386__) || \ +- defined(__x86_64__) || defined(__xtensa__) || defined(__alpha__) || defined(__riscv) ++ defined(__x86_64__) || defined(__xtensa__) || defined(__alpha__) || defined(__riscv) || \ ++ defined(__loongarch__) + /* ctid and newtls are inverted on CONFIG_CLONE_BACKWARDS architectures, + * but since both values are 0, there's no harm. */ + return syscall(__NR_clone, cloneflags, child_stack, ptid, ctid, newtls); +diff --git a/qtbase/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/qtbase/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +index 5792b5b2f5..2f74750fcf 100644 +--- a/qtbase/src/android/jar/src/org/qtproject/qt5/android/QtNative.java ++++ b/qtbase/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +@@ -116,6 +116,7 @@ public class QtNative + public static QtThread m_qtThread = new QtThread(); + private static HashMap m_cachedUris = new HashMap(); + private static ArrayList m_knownDirs = new ArrayList(); ++ private static final String NoPermissionErrorMessage = "No permissions to open Uri"; + + private static final Runnable runPendingCppRunnablesRunnable = new Runnable() { + @Override +@@ -193,11 +194,10 @@ public class QtNative + return iterUri; + } + +- // Android 6 and earlier could still manage to open the file so we can return the +- // parsed uri here +- if (Build.VERSION.SDK_INT < 24) +- return parsedUri; +- return null; ++ // if we only have transient permissions on uri all the above will fail, ++ // but we will be able to read the file anyway, so continue with uri here anyway ++ // and check for SecurityExceptions later ++ return parsedUri; + } catch (SecurityException e) { + e.printStackTrace(); + return null; +@@ -244,7 +244,7 @@ public class QtNative + int error = -1; + + if (uri == null) { +- Log.e(QtTAG, "openFdForContentUrl(): No permissions to open Uri"); ++ Log.e(QtTAG, "openFdForContentUrl(): " + NoPermissionErrorMessage); + return error; + } + +@@ -254,12 +254,13 @@ public class QtNative + return fdDesc.detachFd(); + } catch (FileNotFoundException e) { + e.printStackTrace(); +- return error; + } catch (IllegalArgumentException e) { + Log.e(QtTAG, "openFdForContentUrl(): Invalid Uri"); + e.printStackTrace(); +- return error; ++ } catch (SecurityException e) { ++ Log.e(QtTAG, NoPermissionErrorMessage); + } ++ return error; + } + + public static long getSize(Context context, String contentUrl) +@@ -270,7 +271,7 @@ public class QtNative + uri = getUriWithValidPermission(context, contentUrl, "r"); + + if (uri == null) { +- Log.e(QtTAG, "getSize(): No permissions to open Uri"); ++ Log.e(QtTAG, NoPermissionErrorMessage); + return size; + } else if (!m_cachedUris.containsKey(contentUrl)) { + m_cachedUris.put(contentUrl, uri); +@@ -288,12 +289,13 @@ public class QtNative + } catch (IllegalArgumentException e) { + Log.e(QtTAG, "getSize(): Invalid Uri"); + e.printStackTrace(); +- return size; + } catch (UnsupportedOperationException e) { + Log.e(QtTAG, "getSize(): Unsupported operation for given Uri"); + e.printStackTrace(); +- return size; ++ } catch (SecurityException e) { ++ Log.e(QtTAG, NoPermissionErrorMessage); + } ++ return size; + } + + public static boolean checkFileExists(Context context, String contentUrl) +@@ -303,7 +305,7 @@ public class QtNative + if (uri == null) + uri = getUriWithValidPermission(context, contentUrl, "r"); + if (uri == null) { +- Log.e(QtTAG, "checkFileExists(): No permissions to open Uri"); ++ Log.e(QtTAG, NoPermissionErrorMessage); + return exists; + } else { + if (!m_cachedUris.containsKey(contentUrl)) +@@ -321,12 +323,13 @@ public class QtNative + } catch (IllegalArgumentException e) { + Log.e(QtTAG, "checkFileExists(): Invalid Uri"); + e.printStackTrace(); +- return exists; + } catch (UnsupportedOperationException e) { + Log.e(QtTAG, "checkFileExists(): Unsupported operation for given Uri"); + e.printStackTrace(); +- return false; ++ } catch (SecurityException e) { ++ Log.e(QtTAG, NoPermissionErrorMessage); + } ++ return exists; + } + + public static boolean checkIfWritable(Context context, String contentUrl) +@@ -344,7 +347,7 @@ public class QtNative + uri = getUriWithValidPermission(context, contentUrl, "r"); + } + if (uri == null) { +- Log.e(QtTAG, "isDir(): No permissions to open Uri"); ++ Log.e(QtTAG, NoPermissionErrorMessage); + return isDir; + } else { + if (!m_cachedUris.containsKey(contentUrl)) +@@ -374,12 +377,13 @@ public class QtNative + } catch (IllegalArgumentException e) { + Log.e(QtTAG, "checkIfDir(): Invalid Uri"); + e.printStackTrace(); +- return false; + } catch (UnsupportedOperationException e) { + Log.e(QtTAG, "checkIfDir(): Unsupported operation for given Uri"); + e.printStackTrace(); +- return false; ++ } catch (SecurityException e) { ++ Log.e(QtTAG, NoPermissionErrorMessage); + } ++ return false; + } + public static String[] listContentsFromTreeUri(Context context, String contentUrl) + { +diff --git a/qtbase/src/concurrent/qtconcurrentreducekernel.h b/qtbase/src/concurrent/qtconcurrentreducekernel.h +index 8f9a938952..a98dedef2e 100644 +--- a/qtbase/src/concurrent/qtconcurrentreducekernel.h ++++ b/qtbase/src/concurrent/qtconcurrentreducekernel.h +@@ -212,11 +212,13 @@ public: + + inline bool shouldThrottle() + { ++ std::lock_guard locker(mutex); + return (resultsMapSize > (ReduceQueueThrottleLimit * threadCount)); + } + + inline bool shouldStartThread() + { ++ std::lock_guard locker(mutex); + return (resultsMapSize <= (ReduceQueueStartLimit * threadCount)); + } + }; +diff --git a/qtbase/src/concurrent/qtconcurrentthreadengine.cpp b/qtbase/src/concurrent/qtconcurrentthreadengine.cpp +index ea6ce3ac42..7f91a2ba68 100644 +--- a/qtbase/src/concurrent/qtconcurrentthreadengine.cpp ++++ b/qtbase/src/concurrent/qtconcurrentthreadengine.cpp +@@ -176,6 +176,39 @@ void ThreadEngineBase::startSingleThreaded() + finish(); + } + ++void ThreadEngineBase::startBlocking() ++{ ++ start(); ++ barrier.acquire(); ++ startThreads(); ++ ++ bool throttled = false; ++#ifndef QT_NO_EXCEPTIONS ++ try { ++#endif ++ while (threadFunction() == ThrottleThread) { ++ if (threadThrottleExit()) { ++ throttled = true; ++ break; ++ } ++ } ++#ifndef QT_NO_EXCEPTIONS ++ } catch (QException &e) { ++ handleException(e); ++ } catch (...) { ++ handleException(QUnhandledException()); ++ } ++#endif ++ ++ if (throttled == false) { ++ barrier.release(); ++ } ++ ++ barrier.wait(); ++ finish(); ++ exceptionStore.throwPossibleException(); ++} ++ + void ThreadEngineBase::startThread() + { + startThreadInternal(); +diff --git a/qtbase/src/concurrent/qtconcurrentthreadengine.h b/qtbase/src/concurrent/qtconcurrentthreadengine.h +index 7c30cebdbc..a4c8548cc4 100644 +--- a/qtbase/src/concurrent/qtconcurrentthreadengine.h ++++ b/qtbase/src/concurrent/qtconcurrentthreadengine.h +@@ -91,6 +91,7 @@ public: + ThreadEngineBase(); + virtual ~ThreadEngineBase(); + void startSingleThreaded(); ++ void startBlocking(); + void startThread(); + bool isCanceled(); + void waitForResume(); +@@ -143,6 +144,15 @@ public: + return result(); + } + ++ // Runs the user algorithm using multiple threads. ++ // This function blocks until the algorithm is finished, ++ // and then returns the result. ++ T *startBlocking() ++ { ++ ThreadEngineBase::startBlocking(); ++ return result(); ++ } ++ + // Runs the user algorithm using multiple threads. + // Does not block, returns a future. + QFuture startAsynchronously() +@@ -223,6 +233,13 @@ class ThreadEngineStarter : public ThreadEngineStarterBase + public: + ThreadEngineStarter(TypedThreadEngine *eng) + : Base(eng) { } ++ ++ T startBlocking() ++ { ++ T t = *this->threadEngine->startBlocking(); ++ delete this->threadEngine; ++ return t; ++ } + }; + + // Full template specialization where T is void. +@@ -232,6 +249,12 @@ class ThreadEngineStarter : public ThreadEngineStarterBase + public: + ThreadEngineStarter(ThreadEngine *_threadEngine) + : ThreadEngineStarterBase(_threadEngine) {} ++ ++ void startBlocking() ++ { ++ this->threadEngine->startBlocking(); ++ delete this->threadEngine; ++ } + }; + + //! [qtconcurrentthreadengine-1] +diff --git a/qtbase/src/corelib/animation/qvariantanimation.cpp b/qtbase/src/corelib/animation/qvariantanimation.cpp +index 98b02f0202..eac1524107 100644 +--- a/qtbase/src/corelib/animation/qvariantanimation.cpp ++++ b/qtbase/src/corelib/animation/qvariantanimation.cpp +@@ -276,7 +276,9 @@ void QVariantAnimationPrivate::setCurrentValueForProgress(const qreal progress) + + const qreal startProgress = currentInterval.start.first; + const qreal endProgress = currentInterval.end.first; +- const qreal localProgress = (progress - startProgress) / (endProgress - startProgress); ++ const qreal localProgress = ++ qIsNull(progress - startProgress) ? 0.0 // avoid 0/0 below ++ /* else */ : (progress - startProgress) / (endProgress - startProgress); + + QVariant ret = q->interpolated(currentInterval.start.second, + currentInterval.end.second, +diff --git a/qtbase/src/corelib/global/qnamespace.h b/qtbase/src/corelib/global/qnamespace.h +index ad4150b317..bf19b1627b 100644 +--- a/qtbase/src/corelib/global/qnamespace.h ++++ b/qtbase/src/corelib/global/qnamespace.h +@@ -1864,7 +1864,7 @@ public: + QT_Q_ENUM(TimerType) + QT_Q_ENUM(ScrollPhase) + QT_Q_ENUM(MouseEventSource) +- QT_Q_FLAG(MouseEventFlag) ++ QT_Q_FLAG(MouseEventFlags) + QT_Q_ENUM(ChecksumType) + QT_Q_ENUM(HighDpiScaleFactorRoundingPolicy) + QT_Q_ENUM(TabFocusBehavior) +diff --git a/qtbase/src/corelib/global/qrandom.cpp b/qtbase/src/corelib/global/qrandom.cpp +index 10672c1f92..25f87c7e6a 100644 +--- a/qtbase/src/corelib/global/qrandom.cpp ++++ b/qtbase/src/corelib/global/qrandom.cpp +@@ -383,7 +383,6 @@ struct QRandomGenerator::SystemAndGlobalGenerators + + constexpr SystemAndGlobalGenerators g = {}; + Q_UNUSED(g); +- Q_STATIC_ASSERT(std::is_literal_type::value); + #endif + } + +diff --git a/qtbase/src/corelib/io/qbuffer.cpp b/qtbase/src/corelib/io/qbuffer.cpp +index 595fcd2724..032c0ddd4b 100644 +--- a/qtbase/src/corelib/io/qbuffer.cpp ++++ b/qtbase/src/corelib/io/qbuffer.cpp +@@ -41,6 +41,8 @@ + #include + #include "private/qiodevice_p.h" + ++#include ++ + QT_BEGIN_NAMESPACE + + /** QBufferPrivate **/ +@@ -366,7 +368,9 @@ qint64 QBuffer::size() const + bool QBuffer::seek(qint64 pos) + { + Q_D(QBuffer); +- if (pos > d->buf->size() && isWritable()) { ++ const auto oldBufSize = d->buf->size(); ++ constexpr qint64 MaxSeekPos = (std::numeric_limits::max)(); ++ if (pos <= MaxSeekPos && pos > oldBufSize && isWritable()) { + if (seek(d->buf->size())) { + const qint64 gapSize = pos - d->buf->size(); + if (write(QByteArray(gapSize, 0)) != gapSize) { +@@ -377,7 +381,7 @@ bool QBuffer::seek(qint64 pos) + return false; + } + } else if (pos > d->buf->size() || pos < 0) { +- qWarning("QBuffer::seek: Invalid pos: %d", int(pos)); ++ qWarning("QBuffer::seek: Invalid pos: %lld", pos); + return false; + } + return QIODevice::seek(pos); +diff --git a/qtbase/src/corelib/io/qfilesystemengine_win.cpp b/qtbase/src/corelib/io/qfilesystemengine_win.cpp +index 81d3a71986..c86ed1f9b0 100644 +--- a/qtbase/src/corelib/io/qfilesystemengine_win.cpp ++++ b/qtbase/src/corelib/io/qfilesystemengine_win.cpp +@@ -664,14 +664,14 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry) + return QFileSystemEntry(ret, QFileSystemEntry::FromInternalPath()); + } + +-#if defined(Q_CC_MINGW) && WINVER < 0x0602 // Windows 8 onwards ++#if defined(Q_CC_MINGW) && WINVER < 0x0602 && _WIN32_WINNT < _WIN32_WINNT_WIN8 // Windows 8 onwards + + typedef struct _FILE_ID_INFO { + ULONGLONG VolumeSerialNumber; + FILE_ID_128 FileId; + } FILE_ID_INFO, *PFILE_ID_INFO; + +-#endif // if defined (Q_CC_MINGW) && WINVER < 0x0602 ++#endif // if defined(Q_CC_MINGW) && WINVER < 0x0602 && _WIN32_WINNT < _WIN32_WINNT_WIN8 + + // File ID for Windows up to version 7 and FAT32 drives + static inline QByteArray fileId(HANDLE handle) +diff --git a/qtbase/src/corelib/io/qfilesystemwatcher_inotify.cpp b/qtbase/src/corelib/io/qfilesystemwatcher_inotify.cpp +index 94d9d06bcb..27e0b13b0b 100644 +--- a/qtbase/src/corelib/io/qfilesystemwatcher_inotify.cpp ++++ b/qtbase/src/corelib/io/qfilesystemwatcher_inotify.cpp +@@ -366,7 +366,9 @@ void QInotifyFileSystemWatcherEngine::readFromInotify() + // qDebug("QInotifyFileSystemWatcherEngine::readFromInotify"); + + int buffSize = 0; +- ioctl(inotifyFd, FIONREAD, (char *) &buffSize); ++ if (ioctl(inotifyFd, FIONREAD, (char *) &buffSize) == -1 || buffSize == 0) ++ return; ++ + QVarLengthArray buffer(buffSize); + buffSize = read(inotifyFd, buffer.data(), buffSize); + char *at = buffer.data(); +diff --git a/qtbase/src/corelib/io/qlockfile_win.cpp b/qtbase/src/corelib/io/qlockfile_win.cpp +index 277f8d4230..38ecef5550 100644 +--- a/qtbase/src/corelib/io/qlockfile_win.cpp ++++ b/qtbase/src/corelib/io/qlockfile_win.cpp +@@ -48,6 +48,8 @@ + #include "QtCore/qdebug.h" + #include "QtCore/qthread.h" + ++#include "private/qsystemlibrary_p.h" ++ + QT_BEGIN_NAMESPACE + + static inline bool fileExists(const wchar_t *fileName) +@@ -150,7 +152,7 @@ QString QLockFilePrivate::processNameByPid(qint64 pid) + #if !defined(Q_OS_WINRT) + typedef DWORD (WINAPI *GetModuleFileNameExFunc)(HANDLE, HMODULE, LPTSTR, DWORD); + +- HMODULE hPsapi = LoadLibraryA("psapi"); ++ HMODULE hPsapi = QSystemLibrary::load(L"psapi"); + if (!hPsapi) + return QString(); + GetModuleFileNameExFunc qGetModuleFileNameEx = reinterpret_cast( +diff --git a/qtbase/src/corelib/io/qprocess_unix.cpp b/qtbase/src/corelib/io/qprocess_unix.cpp +index 50390e57f5..15c8f30745 100644 +--- a/qtbase/src/corelib/io/qprocess_unix.cpp ++++ b/qtbase/src/corelib/io/qprocess_unix.cpp +@@ -1,7 +1,7 @@ + /**************************************************************************** + ** + ** Copyright (C) 2016 The Qt Company Ltd. +-** Copyright (C) 2016 Intel Corporation. ++** Copyright (C) 2022 Intel Corporation. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the QtCore module of the Qt Toolkit. +@@ -422,14 +422,15 @@ void QProcessPrivate::startProcess() + // Add the program name to the argument list. + argv[0] = nullptr; + if (!program.contains(QLatin1Char('/'))) { ++ // findExecutable() returns its argument if it's an absolute path, ++ // otherwise it searches $PATH; returns empty if not found (we handle ++ // that case much later) + const QString &exeFilePath = QStandardPaths::findExecutable(program); +- if (!exeFilePath.isEmpty()) { +- const QByteArray &tmp = QFile::encodeName(exeFilePath); +- argv[0] = ::strdup(tmp.constData()); +- } +- } +- if (!argv[0]) ++ const QByteArray &tmp = QFile::encodeName(exeFilePath); ++ argv[0] = ::strdup(tmp.constData()); ++ } else { + argv[0] = ::strdup(encodedProgramName.constData()); ++ } + + // Add every argument to the list + for (int i = 0; i < arguments.count(); ++i) +@@ -983,15 +984,16 @@ bool QProcessPrivate::startDetached(qint64 *pid) + envp = _q_dupEnvironment(environment.d.constData()->vars, &envc); + } + +- QByteArray tmp; + if (!program.contains(QLatin1Char('/'))) { ++ // findExecutable() returns its argument if it's an absolute path, ++ // otherwise it searches $PATH; returns empty if not found (we handle ++ // that case much later) + const QString &exeFilePath = QStandardPaths::findExecutable(program); +- if (!exeFilePath.isEmpty()) +- tmp = QFile::encodeName(exeFilePath); ++ const QByteArray &tmp = QFile::encodeName(exeFilePath); ++ argv[0] = ::strdup(tmp.constData()); ++ } else { ++ argv[0] = ::strdup(QFile::encodeName(program)); + } +- if (tmp.isEmpty()) +- tmp = QFile::encodeName(program); +- argv[0] = tmp.data(); + + if (envp) + qt_safe_execve(argv[0], argv, envp); +diff --git a/qtbase/src/corelib/itemmodels/qabstractitemmodel.cpp b/qtbase/src/corelib/itemmodels/qabstractitemmodel.cpp +index 3a79c502af..997a634e76 100644 +--- a/qtbase/src/corelib/itemmodels/qabstractitemmodel.cpp ++++ b/qtbase/src/corelib/itemmodels/qabstractitemmodel.cpp +@@ -3196,9 +3196,8 @@ bool QAbstractItemModel::beginMoveColumns(const QModelIndex &sourceParent, int s + destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent; + d->changes.push(destinationChange); + +- d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal); +- + emit columnsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal()); ++ d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal); + return true; + } + +@@ -3231,7 +3230,6 @@ void QAbstractItemModel::endMoveColumns() + adjustedSource = createIndex(adjustedSource.row(), adjustedSource.column() + numMoved, adjustedSource.internalPointer()); + + d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Horizontal); +- + emit columnsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal()); + } + +diff --git a/qtbase/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/qtbase/src/corelib/itemmodels/qsortfilterproxymodel.cpp +index dc6379d9fb..c5e287ee84 100644 +--- a/qtbase/src/corelib/itemmodels/qsortfilterproxymodel.cpp ++++ b/qtbase/src/corelib/itemmodels/qsortfilterproxymodel.cpp +@@ -939,8 +939,9 @@ void QSortFilterProxyModelPrivate::insert_source_items( + q->beginInsertColumns(proxy_parent, proxy_start, proxy_end); + } + +- for (int i = 0; i < source_items.size(); ++i) +- proxy_to_source.insert(proxy_start + i, source_items.at(i)); ++ // TODO: use the range QList::insert() overload once it is implemented (QTBUG-58633). ++ proxy_to_source.insert(proxy_start, source_items.size(), 0); ++ std::copy(source_items.cbegin(), source_items.cend(), proxy_to_source.begin() + proxy_start); + + build_source_to_proxy_mapping(proxy_to_source, source_to_proxy); + +@@ -3123,8 +3124,9 @@ bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex & + + if (d->filter_data.isEmpty()) + return true; ++ ++ int column_count = d->model->columnCount(source_parent); + if (d->filter_column == -1) { +- int column_count = d->model->columnCount(source_parent); + for (int column = 0; column < column_count; ++column) { + QModelIndex source_index = d->model->index(source_row, column, source_parent); + QString key = d->model->data(source_index, d->filter_role).toString(); +@@ -3133,9 +3135,10 @@ bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex & + } + return false; + } +- QModelIndex source_index = d->model->index(source_row, d->filter_column, source_parent); +- if (!source_index.isValid()) // the column may not exist ++ ++ if (d->filter_column >= column_count) // the column may not exist + return true; ++ QModelIndex source_index = d->model->index(source_row, d->filter_column, source_parent); + QString key = d->model->data(source_index, d->filter_role).toString(); + return d->filter_data.hasMatch(key); + } +diff --git a/qtbase/src/corelib/kernel/qcoreapplication.cpp b/qtbase/src/corelib/kernel/qcoreapplication.cpp +index ca2864df83..132b2eae52 100644 +--- a/qtbase/src/corelib/kernel/qcoreapplication.cpp ++++ b/qtbase/src/corelib/kernel/qcoreapplication.cpp +@@ -1157,7 +1157,7 @@ static bool doNotify(QObject *receiver, QEvent *event) + bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiver, QEvent *event) + { + // We can't access the application event filters outside of the main thread (race conditions) +- Q_ASSERT(receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread()); ++ Q_ASSERT(receiver->d_func()->threadData.loadAcquire()->thread.loadRelaxed() == mainThread()); + + if (extraData) { + // application event filters are only called for objects in the GUI thread +diff --git a/qtbase/src/corelib/kernel/qobject.cpp b/qtbase/src/corelib/kernel/qobject.cpp +index 1eb79138d9..36cd780ee1 100644 +--- a/qtbase/src/corelib/kernel/qobject.cpp ++++ b/qtbase/src/corelib/kernel/qobject.cpp +@@ -1010,7 +1010,7 @@ QObject::~QObject() + emit destroyed(this); + } + +- if (d->declarativeData) { ++ if (!d->isDeletingChildren && d->declarativeData) { + if (static_cast(d->declarativeData)->ownedByQml1) { + if (QAbstractDeclarativeData::destroyed_qml1) + QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this); +@@ -1580,7 +1580,7 @@ void QObject::moveToThread(QThread *targetThread) + + QThreadData *currentData = QThreadData::current(); + QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : nullptr; +- QThreadData *thisThreadData = d->threadData.loadRelaxed(); ++ QThreadData *thisThreadData = d->threadData.loadAcquire(); + if (!thisThreadData->thread.loadAcquire() && currentData == targetData) { + // one exception to the rule: we allow moving objects with no thread affinity to the current thread + currentData = d->threadData; +@@ -2620,7 +2620,7 @@ int QObject::receivers(const char *signal) const + if (!d->isSignalConnected(signal_index)) + return receivers; + +- if (d->declarativeData && QAbstractDeclarativeData::receivers) { ++ if (!d->isDeletingChildren && d->declarativeData && QAbstractDeclarativeData::receivers) { + receivers += QAbstractDeclarativeData::receivers(d->declarativeData, this, + signal_index); + } +diff --git a/qtbase/src/corelib/kernel/qobject_p.h b/qtbase/src/corelib/kernel/qobject_p.h +index 0b827a52ca..13ffb88999 100644 +--- a/qtbase/src/corelib/kernel/qobject_p.h ++++ b/qtbase/src/corelib/kernel/qobject_p.h +@@ -444,7 +444,7 @@ inline void QObjectPrivate::checkForIncompatibleLibraryVersion(int version) cons + + inline bool QObjectPrivate::isDeclarativeSignalConnected(uint signal_index) const + { +- return declarativeData && QAbstractDeclarativeData::isSignalConnected ++ return !isDeletingChildren && declarativeData && QAbstractDeclarativeData::isSignalConnected + && QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index); + } + +diff --git a/qtbase/src/corelib/kernel/qtranslator.cpp b/qtbase/src/corelib/kernel/qtranslator.cpp +index 2812ffb7ea..bc0177c5ec 100644 +--- a/qtbase/src/corelib/kernel/qtranslator.cpp ++++ b/qtbase/src/corelib/kernel/qtranslator.cpp +@@ -902,7 +902,7 @@ static QString getMessage(const uchar *m, const uchar *end, const char *context, + goto end; + case Tag_Translation: { + int len = read32(m); +- if (len % 1) ++ if (len & 1) + return QString(); + m += 4; + if (!numerus--) { +diff --git a/qtbase/src/corelib/mimetypes/qmimedatabase.cpp b/qtbase/src/corelib/mimetypes/qmimedatabase.cpp +index 9de22cef33..ff868a3268 100644 +--- a/qtbase/src/corelib/mimetypes/qmimedatabase.cpp ++++ b/qtbase/src/corelib/mimetypes/qmimedatabase.cpp +@@ -389,20 +389,23 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa + // Disambiguate conflicting extensions (if magic matching found something) + if (candidateByData.isValid() && magicAccuracy > 0) { + const QString sniffedMime = candidateByData.name(); +- // If the sniffedMime matches a glob match, use it ++ // If the sniffedMime matches a highest-weight glob match, use it + if (candidatesByName.m_matchingMimeTypes.contains(sniffedMime)) { + *accuracyPtr = 100; + return candidateByData; + } +- for (const QString &m : qAsConst(candidatesByName.m_matchingMimeTypes)) { ++ for (const QString &m : qAsConst(candidatesByName.m_allMatchingMimeTypes)) { + if (inherits(m, sniffedMime)) { + // We have magic + pattern pointing to this, so it's a pretty good match + *accuracyPtr = 100; + return mimeTypeForName(m); + } + } +- *accuracyPtr = magicAccuracy; +- return candidateByData; ++ if (candidatesByName.m_allMatchingMimeTypes.isEmpty()) { ++ // No glob, use magic ++ *accuracyPtr = magicAccuracy; ++ return candidateByData; ++ } + } + } + +diff --git a/qtbase/src/corelib/mimetypes/qmimeglobpattern.cpp b/qtbase/src/corelib/mimetypes/qmimeglobpattern.cpp +index a81112d227..fa8f4c545d 100644 +--- a/qtbase/src/corelib/mimetypes/qmimeglobpattern.cpp ++++ b/qtbase/src/corelib/mimetypes/qmimeglobpattern.cpp +@@ -83,7 +83,10 @@ void QMimeGlobMatchResult::addMatch(const QString &mimeType, int weight, const Q + } + if (!m_matchingMimeTypes.contains(mimeType)) { + m_matchingMimeTypes.append(mimeType); +- m_allMatchingMimeTypes.append(mimeType); ++ if (replace) ++ m_allMatchingMimeTypes.prepend(mimeType); // highest-weight first ++ else ++ m_allMatchingMimeTypes.append(mimeType); + m_knownSuffixLength = knownSuffixLength; + } + } +@@ -94,7 +97,7 @@ QMimeGlobPattern::PatternType QMimeGlobPattern::detectPatternType(const QString + if (!patternLength) + return OtherPattern; + +- const bool starCount = pattern.count(QLatin1Char('*')) == 1; ++ const int starCount = pattern.count(QLatin1Char('*')); + const bool hasSquareBracket = pattern.indexOf(QLatin1Char('[')) != -1; + const bool hasQuestionMark = pattern.indexOf(QLatin1Char('?')) != -1; + +@@ -106,10 +109,10 @@ QMimeGlobPattern::PatternType QMimeGlobPattern::detectPatternType(const QString + // Patterns like "README*" (well this is currently the only one like that...) + if (pattern.at(patternLength - 1) == QLatin1Char('*')) + return PrefixPattern; +- } +- // Names without any wildcards like "README" +- if (starCount == 0) ++ } else if (starCount == 0) { ++ // Names without any wildcards like "README" + return LiteralPattern; ++ } + } + + if (pattern == QLatin1String("[0-9][0-9][0-9].vdr")) +diff --git a/qtbase/src/corelib/mimetypes/qmimeprovider.cpp b/qtbase/src/corelib/mimetypes/qmimeprovider.cpp +index 258dddf8cb..4642d0f2d0 100644 +--- a/qtbase/src/corelib/mimetypes/qmimeprovider.cpp ++++ b/qtbase/src/corelib/mimetypes/qmimeprovider.cpp +@@ -244,15 +244,18 @@ void QMimeBinaryProvider::addFileNameMatches(const QString &fileName, QMimeGlobM + const QString lowerFileName = fileName.toLower(); + // Check literals (e.g. "Makefile") + matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosLiteralListOffset), fileName); +- // Check complex globs (e.g. "callgrind.out[0-9]*") +- matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosGlobListOffset), fileName); + // Check the very common *.txt cases with the suffix tree +- const int reverseSuffixTreeOffset = m_cacheFile->getUint32(PosReverseSuffixTreeOffset); +- const int numRoots = m_cacheFile->getUint32(reverseSuffixTreeOffset); +- const int firstRootOffset = m_cacheFile->getUint32(reverseSuffixTreeOffset + 4); +- matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, lowerFileName, lowerFileName.length() - 1, false); ++ if (result.m_matchingMimeTypes.isEmpty()) { ++ const int reverseSuffixTreeOffset = m_cacheFile->getUint32(PosReverseSuffixTreeOffset); ++ const int numRoots = m_cacheFile->getUint32(reverseSuffixTreeOffset); ++ const int firstRootOffset = m_cacheFile->getUint32(reverseSuffixTreeOffset + 4); ++ matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, lowerFileName, lowerFileName.length() - 1, false); ++ if (result.m_matchingMimeTypes.isEmpty()) ++ matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, fileName, fileName.length() - 1, true); ++ } ++ // Check complex globs (e.g. "callgrind.out[0-9]*" or "README*") + if (result.m_matchingMimeTypes.isEmpty()) +- matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, fileName, fileName.length() - 1, true); ++ matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosGlobListOffset), fileName); + } + + void QMimeBinaryProvider::matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int off, const QString &fileName) +diff --git a/qtbase/src/corelib/serialization/qjsonparser.cpp b/qtbase/src/corelib/serialization/qjsonparser.cpp +index 17e6f111ab..2e40b6c8fb 100644 +--- a/qtbase/src/corelib/serialization/qjsonparser.cpp ++++ b/qtbase/src/corelib/serialization/qjsonparser.cpp +@@ -379,10 +379,30 @@ error: + return QCborValue(); + } + ++// We need to retain the _last_ value for any duplicate keys and we need to deref containers. ++// Therefore the manual implementation of std::unique(). ++template ++static Iterator customAssigningUniqueLast(Iterator first, Iterator last, ++ Compare compare, Assign assign) ++{ ++ first = std::adjacent_find(first, last, compare); ++ if (first == last) ++ return last; ++ ++ Iterator result = first; ++ while (++first != last) { ++ if (!compare(*result, *first)) ++ ++result; ++ if (result != first) ++ assign(*result, *first); ++ } ++ ++ return ++result; ++} ++ + static void sortContainer(QCborContainerPrivate *container) + { + using Forward = QJsonPrivate::KeyIterator; +- using Reverse = std::reverse_iterator; + using Value = Forward::value_type; + + auto compare = [container](const Value &a, const Value &b) +@@ -420,17 +440,31 @@ static void sortContainer(QCborContainerPrivate *container) + } + }; + +- std::sort(Forward(container->elements.begin()), Forward(container->elements.end()), +- [&compare](const Value &a, const Value &b) { return compare(a, b) < 0; }); ++ // The elements' containers are owned by the outer container, not by the elements themselves. ++ auto move = [](Forward::reference target, Forward::reference source) ++ { ++ QtCbor::Element &targetValue = target.value(); ++ ++ // If the target has a container, deref it before overwriting, so that we don't leak. ++ if (targetValue.flags & QtCbor::Element::IsContainer) ++ targetValue.container->deref(); ++ ++ // Do not move, so that we can clear the value afterwards. ++ target = source; ++ ++ // Clear the source value, so that we don't store the same container twice. ++ source.value() = QtCbor::Element(); ++ }; ++ ++ std::stable_sort( ++ Forward(container->elements.begin()), Forward(container->elements.end()), ++ [&compare](const Value &a, const Value &b) { return compare(a, b) < 0; }); + +- // We need to retain the _last_ value for any duplicate keys. Therefore the reverse dance here. +- auto it = std::unique(Reverse(container->elements.end()), Reverse(container->elements.begin()), +- [&compare](const Value &a, const Value &b) { +- return compare(a, b) == 0; +- }).base().elementsIterator(); ++ Forward result = customAssigningUniqueLast( ++ Forward(container->elements.begin()), Forward(container->elements.end()), ++ [&compare](const Value &a, const Value &b) { return compare(a, b) == 0; }, move); + +- // The erase from beginning is expensive but hopefully rare. +- container->elements.erase(container->elements.begin(), it); ++ container->elements.erase(result.elementsIterator(), container->elements.end()); + } + + +diff --git a/qtbase/src/corelib/serialization/qxmlstream.cpp b/qtbase/src/corelib/serialization/qxmlstream.cpp +index b2f846544d..7cd457ba3a 100644 +--- a/qtbase/src/corelib/serialization/qxmlstream.cpp ++++ b/qtbase/src/corelib/serialization/qxmlstream.cpp +@@ -980,7 +980,7 @@ inline uint QXmlStreamReaderPrivate::peekChar() + bool QXmlStreamReaderPrivate::scanUntil(const char *str, short tokenToInject) + { + int pos = textBuffer.size(); +- int oldLineNumber = lineNumber; ++ const auto oldLineNumber = lineNumber; + + uint c; + while ((c = getChar()) != StreamEOF) { +diff --git a/qtbase/src/corelib/text/qstring.cpp b/qtbase/src/corelib/text/qstring.cpp +index 3e88ab4859..8deeae47bb 100644 +--- a/qtbase/src/corelib/text/qstring.cpp ++++ b/qtbase/src/corelib/text/qstring.cpp +@@ -12312,7 +12312,7 @@ static qsizetype qLastIndexOf(Haystack haystack0, qsizetype from, + const auto needle = needle0.data(); + const auto *end = haystack; + haystack += from; +- const std::size_t sl_minus_1 = sl - 1; ++ const std::size_t sl_minus_1 = sl ? sl - 1 : 0; + const auto *n = needle + sl_minus_1; + const auto *h = haystack + sl_minus_1; + std::size_t hashNeedle = 0, hashHaystack = 0; +diff --git a/qtbase/src/corelib/text/qstringiterator_p.h b/qtbase/src/corelib/text/qstringiterator_p.h +index 219589b6e4..1d0c66cc78 100644 +--- a/qtbase/src/corelib/text/qstringiterator_p.h ++++ b/qtbase/src/corelib/text/qstringiterator_p.h +@@ -61,6 +61,8 @@ class QStringIterator + { + QString::const_iterator i, pos, e; + Q_STATIC_ASSERT((std::is_same::value)); ++ static bool less(const QChar *lhs, const QChar *rhs) noexcept ++ { return std::less{}(lhs, rhs); } + public: + explicit QStringIterator(QStringView string, qsizetype idx = 0) + : i(string.begin()), +@@ -95,7 +97,8 @@ public: + + inline void setPosition(QString::const_iterator position) + { +- Q_ASSERT_X(i <= position && position <= e, Q_FUNC_INFO, "position out of bounds"); ++ Q_ASSERT_X(!less(position, i) && !less(e, position), ++ Q_FUNC_INFO, "position out of bounds"); + pos = position; + } + +@@ -103,7 +106,7 @@ public: + + inline bool hasNext() const + { +- return pos < e; ++ return less(pos, e); + } + + inline void advance() +@@ -120,16 +123,20 @@ public: + { + Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item"); + +- if (Q_UNLIKELY((pos++)->isHighSurrogate())) ++ if (Q_UNLIKELY((pos++)->isHighSurrogate())) { ++ Q_ASSERT(hasNext() && pos->isLowSurrogate()); + ++pos; ++ } + } + + inline uint peekNextUnchecked() const + { + Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item"); + +- if (Q_UNLIKELY(pos->isHighSurrogate())) ++ if (Q_UNLIKELY(pos->isHighSurrogate())) { ++ Q_ASSERT(less(pos + 1, e) && pos[1].isLowSurrogate()); + return QChar::surrogateToUcs4(pos[0], pos[1]); ++ } + + return pos->unicode(); + } +@@ -155,8 +162,10 @@ public: + Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item"); + + const QChar cur = *pos++; +- if (Q_UNLIKELY(cur.isHighSurrogate())) ++ if (Q_UNLIKELY(cur.isHighSurrogate())) { ++ Q_ASSERT(hasNext() && pos->isLowSurrogate()); + return QChar::surrogateToUcs4(cur, *pos++); ++ } + return cur.unicode(); + } + +@@ -166,7 +175,7 @@ public: + + const QChar uc = *pos++; + if (Q_UNLIKELY(uc.isSurrogate())) { +- if (Q_LIKELY(uc.isHighSurrogate() && pos < e && pos->isLowSurrogate())) ++ if (Q_LIKELY(uc.isHighSurrogate() && hasNext() && pos->isLowSurrogate())) + return QChar::surrogateToUcs4(uc, *pos++); + return invalidAs; + } +@@ -178,7 +187,7 @@ public: + + inline bool hasPrevious() const + { +- return pos > i; ++ return less(i, pos); + } + + inline void recede() +@@ -196,16 +205,20 @@ public: + { + Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item"); + +- if (Q_UNLIKELY((--pos)->isLowSurrogate())) ++ if (Q_UNLIKELY((--pos)->isLowSurrogate())) { ++ Q_ASSERT(hasPrevious() && pos[-1].isHighSurrogate()); + --pos; ++ } + } + + inline uint peekPreviousUnchecked() const + { + Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item"); + +- if (Q_UNLIKELY(pos[-1].isLowSurrogate())) ++ if (Q_UNLIKELY(pos[-1].isLowSurrogate())) { ++ Q_ASSERT(less(i + 1, pos) && pos[-2].isHighSurrogate()); + return QChar::surrogateToUcs4(pos[-2], pos[-1]); ++ } + return pos[-1].unicode(); + } + +@@ -230,8 +243,10 @@ public: + Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item"); + + const QChar cur = *--pos; +- if (Q_UNLIKELY(cur.isLowSurrogate())) ++ if (Q_UNLIKELY(cur.isLowSurrogate())) { ++ Q_ASSERT(hasPrevious() && pos[-1].isHighSurrogate()); + return QChar::surrogateToUcs4(*--pos, cur); ++ } + return cur.unicode(); + } + +@@ -241,7 +256,7 @@ public: + + const QChar uc = *--pos; + if (Q_UNLIKELY(uc.isSurrogate())) { +- if (Q_LIKELY(uc.isLowSurrogate() && pos > i && pos[-1].isHighSurrogate())) ++ if (Q_LIKELY(uc.isLowSurrogate() && hasPrevious() && pos[-1].isHighSurrogate())) + return QChar::surrogateToUcs4(*--pos, uc); + return invalidAs; + } +diff --git a/qtbase/src/corelib/thread/qfutex_p.h b/qtbase/src/corelib/thread/qfutex_p.h +index f287b752d7..e294537787 100644 +--- a/qtbase/src/corelib/thread/qfutex_p.h ++++ b/qtbase/src/corelib/thread/qfutex_p.h +@@ -52,6 +52,7 @@ + // + + #include ++#include + + QT_BEGIN_NAMESPACE + +@@ -106,16 +107,13 @@ namespace QtLinuxFutex { + inline int _q_futex(int *addr, int op, int val, quintptr val2 = 0, + int *addr2 = nullptr, int val3 = 0) noexcept + { +- // A futex call ensures total ordering on the futex words +- // (in either success or failure of the call). Instruct TSAN accordingly, +- // as TSAN does not understand the futex(2) syscall. +- _q_tsan_release(addr, addr2); ++ QtTsan::futexRelease(addr, addr2); + + // we use __NR_futex because some libcs (like Android's bionic) don't + // provide SYS_futex etc. + int result = syscall(__NR_futex, addr, op | FUTEX_PRIVATE_FLAG, val, val2, addr2, val3); + +- _q_tsan_acquire(addr, addr2); ++ QtTsan::futexAcquire(addr, addr2); + + return result; + } +diff --git a/qtbase/src/corelib/thread/qmutex.cpp b/qtbase/src/corelib/thread/qmutex.cpp +index 310d1cb14f..7097122d8e 100644 +--- a/qtbase/src/corelib/thread/qmutex.cpp ++++ b/qtbase/src/corelib/thread/qmutex.cpp +@@ -152,6 +152,7 @@ public: + + /*! + \enum QMutex::RecursionMode ++ \obsolete Use QRecursiveMutex to create a recursive mutex. + + \value Recursive In this mode, a thread can lock the same mutex + multiple times and the mutex won't be unlocked +@@ -173,6 +174,7 @@ public: + + /*! + Constructs a new mutex. The mutex is created in an unlocked state. ++ \obsolete Use QRecursiveMutex to create a recursive mutex. + + If \a mode is QMutex::Recursive, a thread can lock the same mutex + multiple times and the mutex won't be unlocked until a +@@ -197,7 +199,7 @@ QMutex::QMutex(RecursionMode mode) + QMutex::~QMutex() + { + QMutexData *d = d_ptr.loadRelaxed(); +- if (isRecursive()) { ++ if (QBasicMutex::isRecursive()) { + delete static_cast(d); + } else if (d) { + #ifndef QT_LINUX_FUTEX +diff --git a/qtbase/src/corelib/thread/qmutex.h b/qtbase/src/corelib/thread/qmutex.h +index 73c9e00663..1bae573a03 100644 +--- a/qtbase/src/corelib/thread/qmutex.h ++++ b/qtbase/src/corelib/thread/qmutex.h +@@ -42,6 +42,7 @@ + + #include + #include ++#include + #include + + #if __has_include() +@@ -77,19 +78,37 @@ public: + + // BasicLockable concept + inline void lock() QT_MUTEX_LOCK_NOEXCEPT { ++ QtTsan::mutexPreLock(this, 0u); ++ + if (!fastTryLock()) + lockInternal(); ++ ++ QtTsan::mutexPostLock(this, 0u, 0); + } + + // BasicLockable concept + inline void unlock() noexcept { + Q_ASSERT(d_ptr.loadRelaxed()); //mutex must be locked ++ ++ QtTsan::mutexPreUnlock(this, 0u); ++ + if (!fastTryUnlock()) + unlockInternal(); ++ ++ QtTsan::mutexPostUnlock(this, 0u); + } + + bool tryLock() noexcept { +- return fastTryLock(); ++ unsigned tsanFlags = QtTsan::TryLock; ++ QtTsan::mutexPreLock(this, tsanFlags); ++ ++ const bool success = fastTryLock(); ++ ++ if (!success) ++ tsanFlags |= QtTsan::TryLockFailed; ++ QtTsan::mutexPostLock(this, tsanFlags, 0); ++ ++ return success; + } + + // Lockable concept +@@ -134,8 +153,16 @@ public: + #else + QMutex() { d_ptr.storeRelaxed(nullptr); } + #endif ++#if QT_DEPRECATED_SINCE(5,15) + enum RecursionMode { NonRecursive, Recursive }; ++ QT_DEPRECATED_VERSION_X(5, 15, "Use QRecursiveMutex instead of a recursive QMutex") + explicit QMutex(RecursionMode mode); ++ ++ QT_DEPRECATED_VERSION_X(5, 15, "Use QRecursiveMutex instead of a recursive QMutex") ++ bool isRecursive() const noexcept ++ { return QBasicMutex::isRecursive(); } ++#endif ++ + ~QMutex(); + + // BasicLockable concept +@@ -166,9 +193,6 @@ public: + } + #endif + +- bool isRecursive() const noexcept +- { return QBasicMutex::isRecursive(); } +- + private: + Q_DISABLE_COPY(QMutex) + friend class QMutexLocker; +diff --git a/qtbase/src/corelib/thread/qreadwritelock.cpp b/qtbase/src/corelib/thread/qreadwritelock.cpp +index 8c28507d5a..9dd8503116 100644 +--- a/qtbase/src/corelib/thread/qreadwritelock.cpp ++++ b/qtbase/src/corelib/thread/qreadwritelock.cpp +@@ -155,7 +155,7 @@ QReadWriteLock::QReadWriteLock(RecursionMode recursionMode) + */ + QReadWriteLock::~QReadWriteLock() + { +- auto d = d_ptr.loadRelaxed(); ++ auto d = d_ptr.loadAcquire(); + if (isUncontendedLocked(d)) { + qWarning("QReadWriteLock: destroying locked QReadWriteLock"); + return; +@@ -445,7 +445,7 @@ void QReadWriteLock::unlock() + /*! \internal Helper for QWaitCondition::wait */ + QReadWriteLock::StateForWaitCondition QReadWriteLock::stateForWaitCondition() const + { +- QReadWriteLockPrivate *d = d_ptr.loadRelaxed(); ++ QReadWriteLockPrivate *d = d_ptr.loadAcquire(); + switch (quintptr(d) & StateMask) { + case StateLockedForRead: return LockedForRead; + case StateLockedForWrite: return LockedForWrite; +@@ -453,6 +453,7 @@ QReadWriteLock::StateForWaitCondition QReadWriteLock::stateForWaitCondition() co + + if (!d) + return Unlocked; ++ const auto lock = qt_scoped_lock(d->mutex); + if (d->writerCount > 1) + return RecursivelyLocked; + else if (d->writerCount == 1) +diff --git a/qtbase/src/corelib/thread/qsemaphore.cpp b/qtbase/src/corelib/thread/qsemaphore.cpp +index 1d01fc1b28..3ecdee3747 100644 +--- a/qtbase/src/corelib/thread/qsemaphore.cpp ++++ b/qtbase/src/corelib/thread/qsemaphore.cpp +@@ -354,7 +354,12 @@ void QSemaphore::release(int n) + quintptr nn = unsigned(n); + if (futexHasWaiterCount) + nn |= quint64(nn) << 32; // token count replicated in high word +- quintptr prevValue = u.fetchAndAddRelease(nn); ++ quintptr prevValue = u.loadRelaxed(); ++ quintptr newValue; ++ do { // loop just to ensure the operations are done atomically ++ newValue = prevValue + nn; ++ newValue &= (futexNeedsWakeAllBit - 1); ++ } while (!u.testAndSetRelease(prevValue, newValue, prevValue)); + if (futexNeedsWake(prevValue)) { + #ifdef FUTEX_OP + if (futexHasWaiterCount) { +@@ -376,7 +381,6 @@ void QSemaphore::release(int n) + quint32 oparg = 0; + quint32 cmp = FUTEX_OP_CMP_NE; + quint32 cmparg = 0; +- u.fetchAndAndRelease(futexNeedsWakeAllBit - 1); + futexWakeOp(*futexLow32(&u), n, INT_MAX, *futexHigh32(&u), FUTEX_OP(op, oparg, cmp, cmparg)); + return; + } +@@ -388,7 +392,6 @@ void QSemaphore::release(int n) + // its acquisition anyway, so it has to wait; + // 2) it did not see the new counter value, in which case its + // futexWait will fail. +- u.fetchAndAndRelease(futexNeedsWakeAllBit - 1); + if (futexHasWaiterCount) { + futexWakeAll(*futexLow32(&u)); + futexWakeAll(*futexHigh32(&u)); +diff --git a/qtbase/src/corelib/thread/qthread_p.h b/qtbase/src/corelib/thread/qthread_p.h +index b2d1628e6e..f32f6f0460 100644 +--- a/qtbase/src/corelib/thread/qthread_p.h ++++ b/qtbase/src/corelib/thread/qthread_p.h +@@ -174,7 +174,7 @@ public: + int returnCode; + + uint stackSize; +- QThread::Priority priority; ++ std::underlying_type::type priority; + + static QThread *threadForId(int id); + +@@ -213,6 +213,13 @@ public: + QCoreApplication::instance()->postEvent(q_ptr, new QEvent(QEvent::Quit)); + } + } ++ ++#ifndef Q_OS_INTEGRITY ++private: ++ // Used in QThread(Private)::start to avoid racy access to QObject::objectName, ++ // unset afterwards. On INTEGRITY we set the thread name before starting it. ++ QString objectName; ++#endif + }; + + #else // QT_CONFIG(thread) +diff --git a/qtbase/src/corelib/thread/qthread_unix.cpp b/qtbase/src/corelib/thread/qthread_unix.cpp +index 56a8e0a038..610117a640 100644 +--- a/qtbase/src/corelib/thread/qthread_unix.cpp ++++ b/qtbase/src/corelib/thread/qthread_unix.cpp +@@ -169,8 +169,7 @@ static void set_thread_data(QThreadData *data) + + static void clear_thread_data() + { +- currentThreadData = nullptr; +- pthread_setspecific(current_thread_data_key, nullptr); ++ set_thread_data(nullptr); + } + + template +@@ -296,7 +295,7 @@ void *QThreadPrivate::start(void *arg) + QMutexLocker locker(&thr->d_func()->mutex); + + // do we need to reset the thread priority? +- if (int(thr->d_func()->priority) & ThreadPriorityResetFlag) { ++ if (thr->d_func()->priority & ThreadPriorityResetFlag) { + thr->d_func()->setPriority(QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag)); + } + +@@ -316,10 +315,10 @@ void *QThreadPrivate::start(void *arg) + // Sets the name of the current thread. We can only do this + // when the thread is starting, as we don't have a cross + // platform way of setting the name of an arbitrary thread. +- if (Q_LIKELY(thr->objectName().isEmpty())) ++ if (Q_LIKELY(thr->d_func()->objectName.isEmpty())) + setCurrentThreadName(thr->metaObject()->className()); + else +- setCurrentThreadName(thr->objectName().toLocal8Bit()); ++ setCurrentThreadName(std::exchange(thr->d_func()->objectName, {}).toLocal8Bit()); + } + #endif + +@@ -671,7 +670,7 @@ void QThread::start(Priority priority) + // could not set scheduling hints, fallback to inheriting them + // we'll try again from inside the thread + pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED); +- d->priority = Priority(priority | ThreadPriorityResetFlag); ++ d->priority = static_cast::type>(priority) | ThreadPriorityResetFlag; + } + break; + } +@@ -702,7 +701,10 @@ void QThread::start(Priority priority) + pthread_attr_setthreadname(&attr, metaObject()->className()); + else + pthread_attr_setthreadname(&attr, objectName().toLocal8Bit()); ++#else ++ d->objectName = objectName(); + #endif ++ + pthread_t threadId; + int code = pthread_create(&threadId, &attr, QThreadPrivate::start, this); + if (code == EPERM) { +diff --git a/qtbase/src/corelib/thread/qthread_win.cpp b/qtbase/src/corelib/thread/qthread_win.cpp +index bc70e3178a..4e76972498 100644 +--- a/qtbase/src/corelib/thread/qthread_win.cpp ++++ b/qtbase/src/corelib/thread/qthread_win.cpp +@@ -394,10 +394,9 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi + + #if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINRT) + // sets the name of the current thread. +- QByteArray objectName = thr->objectName().toLocal8Bit(); +- qt_set_thread_name(HANDLE(-1), +- objectName.isEmpty() ? +- thr->metaObject()->className() : objectName.constData()); ++ qt_set_thread_name(HANDLE(-1), thr->d_func()->objectName.isEmpty() ++ ? thr->metaObject()->className() ++ : std::exchange(thr->d_func()->objectName, {}).toLocal8Bit().constData()); + #endif + + emit thr->started(QThread::QPrivateSignal()); +@@ -503,6 +502,7 @@ void QThread::start(Priority priority) + if (d->running) + return; + ++ d->objectName = objectName(); + d->running = true; + d->finished = false; + d->exited = false; +@@ -548,7 +548,7 @@ void QThread::start(Priority priority) + + int prio; + d->priority = priority; +- switch (d->priority) { ++ switch (priority) { + case IdlePriority: + prio = THREAD_PRIORITY_IDLE; + break; +@@ -686,7 +686,7 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority) + + int prio; + priority = threadPriority; +- switch (priority) { ++ switch (threadPriority) { + case QThread::IdlePriority: + prio = THREAD_PRIORITY_IDLE; + break; +diff --git a/qtbase/src/corelib/thread/qtsan_impl.h b/qtbase/src/corelib/thread/qtsan_impl.h +new file mode 100644 +index 0000000000..580a738b91 +--- /dev/null ++++ b/qtbase/src/corelib/thread/qtsan_impl.h +@@ -0,0 +1,115 @@ ++/**************************************************************************** ++** ++** Copyright (C) 2017 Intel Corporation. ++** Copyright (C) 2022 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo ++** Contact: https://www.qt.io/licensing/ ++** ++** This file is part of the QtCore module of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** Commercial License Usage ++** Licensees holding valid commercial Qt licenses may use this file in ++** accordance with the commercial license agreement provided with the ++** Software or, alternatively, in accordance with the terms contained in ++** a written agreement between you and The Qt Company. For licensing terms ++** and conditions see https://www.qt.io/terms-conditions. For further ++** information use the contact form at https://www.qt.io/contact-us. ++** ++** GNU Lesser General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU Lesser ++** General Public License version 3 as published by the Free Software ++** Foundation and appearing in the file LICENSE.LGPL3 included in the ++** packaging of this file. Please review the following information to ++** ensure the GNU Lesser General Public License version 3 requirements ++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU ++** General Public License version 2.0 or (at your option) the GNU General ++** Public license version 3 or any later version approved by the KDE Free ++** Qt Foundation. The licenses are as published by the Free Software ++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ++** included in the packaging of this file. Please review the following ++** information to ensure the GNU General Public License requirements will ++** be met: https://www.gnu.org/licenses/gpl-2.0.html and ++** https://www.gnu.org/licenses/gpl-3.0.html. ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#ifndef QTSAN_IMPL_H ++#define QTSAN_IMPL_H ++ ++#include ++ ++#if (__has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)) && __has_include() ++# define QT_BUILDING_UNDER_TSAN ++# include ++#endif ++ ++QT_BEGIN_NAMESPACE ++ ++namespace QtTsan { ++#ifdef QT_BUILDING_UNDER_TSAN ++inline void futexAcquire(void *addr, void *addr2 = nullptr) ++{ ++ // A futex call ensures total ordering on the futex words ++ // (in either success or failure of the call). Instruct TSAN accordingly, ++ // as TSAN does not understand the futex(2) syscall (or equivalent). ++ ::__tsan_acquire(addr); ++ if (addr2) ++ ::__tsan_acquire(addr2); ++} ++ ++inline void futexRelease(void *addr, void *addr2 = nullptr) ++{ ++ if (addr2) ++ ::__tsan_release(addr2); ++ ::__tsan_release(addr); ++} ++ ++inline void mutexPreLock(void *addr, unsigned flags) ++{ ++ ::__tsan_mutex_pre_lock(addr, flags); ++} ++ ++inline void mutexPostLock(void *addr, unsigned flags, int recursion) ++{ ++ ::__tsan_mutex_post_lock(addr, flags, recursion); ++} ++ ++inline void mutexPreUnlock(void *addr, unsigned flags) ++{ ++ ::__tsan_mutex_pre_unlock(addr, flags); ++} ++ ++inline void mutexPostUnlock(void *addr, unsigned flags) ++{ ++ ::__tsan_mutex_post_unlock(addr, flags); ++} ++ ++enum : unsigned { ++ MutexWriteReentrant = ::__tsan_mutex_write_reentrant, ++ TryLock = ::__tsan_mutex_try_lock, ++ TryLockFailed = ::__tsan_mutex_try_lock_failed, ++}; ++#else ++inline void futexAcquire(void *, void * = nullptr) {} ++inline void futexRelease(void *, void * = nullptr) {} ++ ++enum : unsigned { ++ MutexWriteReentrant, ++ TryLock, ++ TryLockFailed, ++}; ++inline void mutexPreLock(void *, unsigned) {} ++inline void mutexPostLock(void *, unsigned, int) {} ++inline void mutexPreUnlock(void *, unsigned) {} ++inline void mutexPostUnlock(void *, unsigned) {} ++#endif // QT_BUILDING_UNDER_TSAN ++} // namespace QtTsan ++ ++QT_END_NAMESPACE ++ ++#endif // QTSAN_IMPL_H +diff --git a/qtbase/src/corelib/thread/qwaitcondition_unix.cpp b/qtbase/src/corelib/thread/qwaitcondition_unix.cpp +index 88b058f410..0f1da4dc9b 100644 +--- a/qtbase/src/corelib/thread/qwaitcondition_unix.cpp ++++ b/qtbase/src/corelib/thread/qwaitcondition_unix.cpp +@@ -213,7 +213,7 @@ bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline) + { + if (! mutex) + return false; +- if (mutex->isRecursive()) { ++ if (static_cast(mutex)->isRecursive()) { + qWarning("QWaitCondition: cannot wait on recursive mutexes"); + return false; + } +diff --git a/qtbase/src/corelib/time/qdatetime.cpp b/qtbase/src/corelib/time/qdatetime.cpp +index ec12569e3f..2c0b098079 100644 +--- a/qtbase/src/corelib/time/qdatetime.cpp ++++ b/qtbase/src/corelib/time/qdatetime.cpp +@@ -43,6 +43,7 @@ + #if QT_CONFIG(datetimeparser) + #include "private/qdatetimeparser_p.h" + #endif ++#include + + #include "qdatastream.h" + #include "qset.h" +@@ -1429,9 +1430,11 @@ QDate QDate::addDays(qint64 ndays) const + if (isNull()) + return QDate(); + +- // Due to limits on minJd() and maxJd() we know that any overflow +- // will be invalid and caught by fromJulianDay(). +- return fromJulianDay(jd + ndays); ++ qint64 r; ++ if (Q_UNLIKELY(add_overflow(jd, ndays, &r))) ++ return QDate(); ++ else ++ return fromJulianDay(r); + } + + /*! +diff --git a/qtbase/src/corelib/time/qtimezone.cpp b/qtbase/src/corelib/time/qtimezone.cpp +index 0309e43e52..3d451696a1 100644 +--- a/qtbase/src/corelib/time/qtimezone.cpp ++++ b/qtbase/src/corelib/time/qtimezone.cpp +@@ -1,6 +1,6 @@ + /**************************************************************************** + ** +-** Copyright (C) 2013 John Layt ++** Copyright (C) 2020 John Layt + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the QtCore module of the Qt Toolkit. +@@ -975,9 +975,15 @@ QList QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId, + } + + #ifndef QT_NO_DATASTREAM ++// Invalid, as an IANA ID: too long, starts with - and has other invalid characters in it ++static inline QString invalidId() { return QStringLiteral("-No Time Zone Specified!"); } ++ + QDataStream &operator<<(QDataStream &ds, const QTimeZone &tz) + { +- tz.d->serialize(ds); ++ if (tz.isValid()) ++ tz.d->serialize(ds); ++ else ++ ds << invalidId(); + return ds; + } + +@@ -985,7 +991,9 @@ QDataStream &operator>>(QDataStream &ds, QTimeZone &tz) + { + QString ianaId; + ds >> ianaId; +- if (ianaId == QLatin1String("OffsetFromUtc")) { ++ if (ianaId == invalidId()) { ++ tz = QTimeZone(); ++ } else if (ianaId == QLatin1String("OffsetFromUtc")) { + int utcOffset; + QString name; + QString abbreviation; +diff --git a/qtbase/src/corelib/time/qtimezoneprivate_tz.cpp b/qtbase/src/corelib/time/qtimezoneprivate_tz.cpp +index b1611d7ddb..a7a6a72ccf 100644 +--- a/qtbase/src/corelib/time/qtimezoneprivate_tz.cpp ++++ b/qtbase/src/corelib/time/qtimezoneprivate_tz.cpp +@@ -42,6 +42,7 @@ + #include "qtimezone.h" + #include "qtimezoneprivate_p.h" + #include "private/qlocale_tools_p.h" ++#include "private/qlocking_p.h" + + #include + #include +@@ -62,6 +63,10 @@ + + QT_BEGIN_NAMESPACE + ++#if QT_CONFIG(icu) ++static QBasicMutex s_icu_mutex; ++#endif ++ + /* + Private + +@@ -670,6 +675,9 @@ QTzTimeZonePrivate::~QTzTimeZonePrivate() + + QTzTimeZonePrivate *QTzTimeZonePrivate::clone() const + { ++#if QT_CONFIG(icu) ++ const auto lock = qt_scoped_lock(s_icu_mutex); ++#endif + return new QTzTimeZonePrivate(*this); + } + +@@ -913,12 +921,14 @@ QString QTzTimeZonePrivate::displayName(qint64 atMSecsSinceEpoch, + const QLocale &locale) const + { + #if QT_CONFIG(icu) ++ auto lock = qt_unique_lock(s_icu_mutex); + if (!m_icu) + m_icu = new QIcuTimeZonePrivate(m_id); + // TODO small risk may not match if tran times differ due to outdated files + // TODO Some valid TZ names are not valid ICU names, use translation table? + if (m_icu->isValid()) + return m_icu->displayName(atMSecsSinceEpoch, nameType, locale); ++ lock.unlock(); + #else + Q_UNUSED(nameType) + Q_UNUSED(locale) +@@ -932,12 +942,14 @@ QString QTzTimeZonePrivate::displayName(QTimeZone::TimeType timeType, + const QLocale &locale) const + { + #if QT_CONFIG(icu) ++ auto lock = qt_unique_lock(s_icu_mutex); + if (!m_icu) + m_icu = new QIcuTimeZonePrivate(m_id); + // TODO small risk may not match if tran times differ due to outdated files + // TODO Some valid TZ names are not valid ICU names, use translation table? + if (m_icu->isValid()) + return m_icu->displayName(timeType, nameType, locale); ++ lock.unlock(); + #else + Q_UNUSED(timeType) + Q_UNUSED(nameType) +diff --git a/qtbase/src/corelib/tools/qarraydata.h b/qtbase/src/corelib/tools/qarraydata.h +index dcd95924c1..d01739e7e6 100644 +--- a/qtbase/src/corelib/tools/qarraydata.h ++++ b/qtbase/src/corelib/tools/qarraydata.h +@@ -42,6 +42,7 @@ + + #include + #include ++#include + + QT_BEGIN_NAMESPACE + +@@ -58,14 +59,14 @@ struct Q_CORE_EXPORT QArrayData + { + Q_ASSERT(size == 0 + || offset < 0 || size_t(offset) >= sizeof(QArrayData)); +- return reinterpret_cast(this) + offset; ++ return reinterpret_cast (reinterpret_cast(this) + offset); + } + + const void *data() const + { + Q_ASSERT(size == 0 + || offset < 0 || size_t(offset) >= sizeof(QArrayData)); +- return reinterpret_cast(this) + offset; ++ return reinterpret_cast (reinterpret_cast(this) + offset); + } + + // This refers to array data mutability, not "header data" represented by +diff --git a/qtbase/src/corelib/tools/qfreelist_p.h b/qtbase/src/corelib/tools/qfreelist_p.h +index 5ba23b344b..9974102136 100644 +--- a/qtbase/src/corelib/tools/qfreelist_p.h ++++ b/qtbase/src/corelib/tools/qfreelist_p.h +@@ -161,7 +161,7 @@ class QFreeList + return i; + x -= size; + } +- Q_ASSERT(false); ++ Q_UNREACHABLE(); + return -1; + } + +diff --git a/qtbase/src/corelib/tools/qversionnumber.h b/qtbase/src/corelib/tools/qversionnumber.h +index d43b86ba51..2843f2b043 100644 +--- a/qtbase/src/corelib/tools/qversionnumber.h ++++ b/qtbase/src/corelib/tools/qversionnumber.h +@@ -273,10 +273,10 @@ public: + + Q_REQUIRED_RESULT Q_CORE_EXPORT QString toString() const; + #if QT_STRINGVIEW_LEVEL < 2 +- Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(const QString &string, int *suffixIndex = nullptr); ++ Q_REQUIRED_RESULT Q_CORE_EXPORT static QVersionNumber fromString(const QString &string, int *suffixIndex = nullptr); + #endif +- Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(QLatin1String string, int *suffixIndex = nullptr); +- Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(QStringView string, int *suffixIndex = nullptr); ++ Q_REQUIRED_RESULT Q_CORE_EXPORT static QVersionNumber fromString(QLatin1String string, int *suffixIndex = nullptr); ++ Q_REQUIRED_RESULT Q_CORE_EXPORT static QVersionNumber fromString(QStringView string, int *suffixIndex = nullptr); + + private: + #ifndef QT_NO_DATASTREAM +diff --git a/qtbase/src/dbus/qdbusintegrator.cpp b/qtbase/src/dbus/qdbusintegrator.cpp +index 5b66ce971b..28a3b0ffea 100644 +--- a/qtbase/src/dbus/qdbusintegrator.cpp ++++ b/qtbase/src/dbus/qdbusintegrator.cpp +@@ -1135,7 +1135,13 @@ void QDBusConnectionPrivate::closeConnection() + } + } + +- qDeleteAll(pendingCalls); ++ for (auto it = pendingCalls.begin(); it != pendingCalls.end(); ++it) { ++ auto call = *it; ++ if (!call->ref.deref()) { ++ delete call; ++ } ++ } ++ pendingCalls.clear(); + + // Disconnect all signals from signal hooks and from the object tree to + // avoid QObject::destroyed being sent to dbus daemon thread which has +@@ -2584,6 +2590,11 @@ QDBusConnectionPrivate::findMetaObject(const QString &service, const QString &pa + if (mo) + return mo; + } ++ if (path.isEmpty()) { ++ error = QDBusError(QDBusError::InvalidObjectPath, QLatin1String("Object path cannot be empty")); ++ lastError = error; ++ return nullptr; ++ } + + // introspect the target object + QDBusMessage msg = QDBusMessage::createMethodCall(service, path, +diff --git a/qtbase/src/dbus/qdbusmetaobject.cpp b/qtbase/src/dbus/qdbusmetaobject.cpp +index 5265568f42..7e9f0f1acc 100644 +--- a/qtbase/src/dbus/qdbusmetaobject.cpp ++++ b/qtbase/src/dbus/qdbusmetaobject.cpp +@@ -210,6 +210,9 @@ QDBusMetaObjectGenerator::findType(const QByteArray &signature, + } else if (signature == "a{ss}") { + result.name = "QMap"; + type = qMetaTypeId >(); ++ } else if (signature == "aay") { ++ result.name = "QByteArrayList"; ++ type = qMetaTypeId(); + } else { + result.name = "{D-Bus type \"" + signature + "\"}"; + type = registerComplexDBusType(result.name); +diff --git a/qtbase/src/gui/accessible/qaccessible.cpp b/qtbase/src/gui/accessible/qaccessible.cpp +index d705bfccb5..0caf3c808c 100644 +--- a/qtbase/src/gui/accessible/qaccessible.cpp ++++ b/qtbase/src/gui/accessible/qaccessible.cpp +@@ -54,6 +54,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -681,6 +682,25 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object) + // Create a QAccessibleInterface for the object class. Start by the most + // derived class and walk up the class hierarchy. + const QMetaObject *mo = object->metaObject(); ++ const auto *objectPriv = QObjectPrivate::get(object); ++ /* ++ We do not want to cache each and every QML metaobject (Button_QMLTYPE_124, ++ Button_QMLTYPE_125, etc.). Those dynamic metaobjects shouldn't have an ++ accessible interface in any case. Instead, we start the whole checking ++ with the first non-dynamic meta-object. To avoid potential regressions ++ in other areas of Qt that also use dynamic metaobjects, we only do this ++ for objects that are QML-related (approximated by checking whether they ++ have ddata set). ++ */ ++ const bool qmlRelated = !objectPriv->isDeletingChildren && ++ objectPriv->declarativeData; ++ while (qmlRelated && mo) { ++ auto mop = QMetaObjectPrivate::get(mo); ++ if (!mop || !(mop->flags & DynamicMetaObject)) ++ break; ++ ++ mo = mo->superClass(); ++ }; + while (mo) { + const QString cn = QLatin1String(mo->className()); + +@@ -696,14 +716,15 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object) + // Find a QAccessiblePlugin (factory) for the class name. If there's + // no entry in the cache try to create it using the plugin loader. + if (!qAccessiblePlugins()->contains(cn)) { ++ QAccessiblePlugin *factory = nullptr; // 0 means "no plugin found". This is cached as well. + const int index = loader()->indexOf(cn); +- if (index != -1) { +- QAccessiblePlugin *factory = qobject_cast(loader()->instance(index)); +- qAccessiblePlugins()->insert(cn, factory); +- } ++ if (index != -1) ++ factory = qobject_cast(loader()->instance(index)); ++ qAccessiblePlugins()->insert(cn, factory); + } + + // At this point the cache should contain a valid factory pointer or 0: ++ Q_ASSERT(qAccessiblePlugins()->contains(cn)); + QAccessiblePlugin *factory = qAccessiblePlugins()->value(cn); + if (factory) { + QAccessibleInterface *result = factory->create(cn, object); +diff --git a/qtbase/src/gui/configure.json b/qtbase/src/gui/configure.json +index 1f08795c57..12c95742d2 100644 +--- a/qtbase/src/gui/configure.json ++++ b/qtbase/src/gui/configure.json +@@ -834,7 +834,8 @@ + "// embedded devices, are not intended to be used together with X. EGL support", + "// has to be disabled in plugins like xcb in this case since the native display,", + "// window and pixmap types will be different than what an X-based platform", +- "// plugin would expect." ++ "// plugin would expect.", ++ "#define USE_X11" + ], + "include": [ "EGL/egl.h", "X11/Xlib.h" ], + "main": [ +diff --git a/qtbase/src/gui/image/qbmphandler.cpp b/qtbase/src/gui/image/qbmphandler.cpp +index 96f1e8cb1d..0e73bbbdb0 100644 +--- a/qtbase/src/gui/image/qbmphandler.cpp ++++ b/qtbase/src/gui/image/qbmphandler.cpp +@@ -150,16 +150,42 @@ static QDataStream &operator<<(QDataStream &s, const BMP_INFOHDR &bi) + return s; + } + +-static int calc_shift(uint mask) ++static uint calc_shift(uint mask) + { +- int result = 0; +- while (mask && !(mask & 1)) { ++ uint result = 0; ++ while ((mask >= 0x100) || (!(mask & 1) && mask)) { + result++; + mask >>= 1; + } + return result; + } + ++static uint calc_scale(uint low_mask) ++{ ++ uint result = 8; ++ while (low_mask && result) { ++ result--; ++ low_mask >>= 1; ++ } ++ return result; ++} ++ ++static inline uint apply_scale(uint value, uint scale) ++{ ++ if (!(scale & 0x07)) // return immediately if scale == 8 or 0 ++ return value; ++ ++ uint filled = 8 - scale; ++ uint result = value << scale; ++ ++ do { ++ result |= result >> filled; ++ filled <<= 1; ++ } while (filled < 8); ++ ++ return result; ++} ++ + static bool read_dib_fileheader(QDataStream &s, BMP_FILEHDR &bf) + { + // read BMP file header +@@ -222,14 +248,14 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset, + uint green_mask = 0; + uint blue_mask = 0; + uint alpha_mask = 0; +- int red_shift = 0; +- int green_shift = 0; +- int blue_shift = 0; +- int alpha_shift = 0; +- int red_scale = 0; +- int green_scale = 0; +- int blue_scale = 0; +- int alpha_scale = 0; ++ uint red_shift = 0; ++ uint green_shift = 0; ++ uint blue_shift = 0; ++ uint alpha_shift = 0; ++ uint red_scale = 0; ++ uint green_scale = 0; ++ uint blue_scale = 0; ++ uint alpha_scale = 0; + + if (!d->isSequential()) + d->seek(startpos + BMP_FILEHDR_SIZE + bi.biSize); // goto start of colormap or masks +@@ -308,19 +334,19 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset, + red_shift = calc_shift(red_mask); + if (((red_mask >> red_shift) + 1) == 0) + return false; +- red_scale = 256 / ((red_mask >> red_shift) + 1); ++ red_scale = calc_scale(red_mask >> red_shift); + green_shift = calc_shift(green_mask); + if (((green_mask >> green_shift) + 1) == 0) + return false; +- green_scale = 256 / ((green_mask >> green_shift) + 1); ++ green_scale = calc_scale(green_mask >> green_shift); + blue_shift = calc_shift(blue_mask); + if (((blue_mask >> blue_shift) + 1) == 0) + return false; +- blue_scale = 256 / ((blue_mask >> blue_shift) + 1); ++ blue_scale = calc_scale(blue_mask >> blue_shift); + alpha_shift = calc_shift(alpha_mask); + if (((alpha_mask >> alpha_shift) + 1) == 0) + return false; +- alpha_scale = 256 / ((alpha_mask >> alpha_shift) + 1); ++ alpha_scale = calc_scale(alpha_mask >> alpha_shift); + } else if (comp == BMP_RGB && (nbits == 24 || nbits == 32)) { + blue_mask = 0x000000ff; + green_mask = 0x0000ff00; +@@ -328,17 +354,15 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset, + blue_shift = 0; + green_shift = 8; + red_shift = 16; +- blue_scale = green_scale = red_scale = 1; ++ blue_scale = green_scale = red_scale = 0; + } else if (comp == BMP_RGB && nbits == 16) { + blue_mask = 0x001f; + green_mask = 0x03e0; + red_mask = 0x7c00; + blue_shift = 0; +- green_shift = 2; +- red_shift = 7; +- red_scale = 1; +- green_scale = 1; +- blue_scale = 8; ++ green_shift = 5; ++ red_shift = 10; ++ blue_scale = green_scale = red_scale = 3; + } + + #if 0 +@@ -544,10 +568,10 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset, + c |= *(uchar*)(b+2)<<16; + if (nbits > 24) + c |= *(uchar*)(b+3)<<24; +- *p++ = qRgba(((c & red_mask) >> red_shift) * red_scale, +- ((c & green_mask) >> green_shift) * green_scale, +- ((c & blue_mask) >> blue_shift) * blue_scale, +- transp ? ((c & alpha_mask) >> alpha_shift) * alpha_scale : 0xff); ++ *p++ = qRgba(apply_scale((c & red_mask) >> red_shift, red_scale), ++ apply_scale((c & green_mask) >> green_shift, green_scale), ++ apply_scale((c & blue_mask) >> blue_shift, blue_scale), ++ transp ? apply_scale((c & alpha_mask) >> alpha_shift, alpha_scale) : 0xff); + b += nbits/8; + } + } +diff --git a/qtbase/src/gui/image/qimage.cpp b/qtbase/src/gui/image/qimage.cpp +index 7152ac1607..0df772564c 100644 +--- a/qtbase/src/gui/image/qimage.cpp ++++ b/qtbase/src/gui/image/qimage.cpp +@@ -4694,6 +4694,8 @@ QImage QImage::smoothScaled(int w, int h) const { + static QImage rotated90(const QImage &image) + { + QImage out(image.height(), image.width(), image.format()); ++ if (out.isNull()) ++ return out; + copyMetadata(&out, image); + if (image.colorCount() > 0) + out.setColorTable(image.colorTable()); +@@ -4722,6 +4724,8 @@ static QImage rotated180(const QImage &image) + return image.mirrored(true, true); + + QImage out(image.width(), image.height(), image.format()); ++ if (out.isNull()) ++ return out; + copyMetadata(&out, image); + if (image.colorCount() > 0) + out.setColorTable(image.colorTable()); +@@ -4734,6 +4738,8 @@ static QImage rotated180(const QImage &image) + static QImage rotated270(const QImage &image) + { + QImage out(image.height(), image.width(), image.format()); ++ if (out.isNull()) ++ return out; + copyMetadata(&out, image); + if (image.colorCount() > 0) + out.setColorTable(image.colorTable()); +diff --git a/qtbase/src/gui/kernel/qcursor.cpp b/qtbase/src/gui/kernel/qcursor.cpp +index d6ccaff8ed..455088241c 100644 +--- a/qtbase/src/gui/kernel/qcursor.cpp ++++ b/qtbase/src/gui/kernel/qcursor.cpp +@@ -251,7 +251,8 @@ void QCursor::setPos(QScreen *screen, int x, int y) + { + if (screen) { + if (QPlatformCursor *cursor = screen->handle()->cursor()) { +- const QPoint devicePos = QHighDpi::toNativePixels(QPoint(x, y), screen); ++ const QPoint pos(x, y); ++ const QPoint devicePos = QHighDpi::toNativePixels(pos, screen->virtualSiblingAt(pos)); + // Need to check, since some X servers generate null mouse move + // events, causing looping in applications which call setPos() on + // every mouse move event. +diff --git a/qtbase/src/gui/kernel/qhighdpiscaling.cpp b/qtbase/src/gui/kernel/qhighdpiscaling.cpp +index 9bbf2773a9..3ac4a4d8b6 100644 +--- a/qtbase/src/gui/kernel/qhighdpiscaling.cpp ++++ b/qtbase/src/gui/kernel/qhighdpiscaling.cpp +@@ -580,9 +580,8 @@ void QHighDpiScaling::setScreenFactor(QScreen *screen, qreal factor) + else + qNamedScreenScaleFactors()->insert(name, factor); + +- // hack to force re-evaluation of screen geometry + if (screen->handle()) +- screen->d_func()->setPlatformScreen(screen->handle()); // updates geometries based on scale factor ++ screen->d_func()->updateLogicalDpi(); + } + + QPoint QHighDpiScaling::mapPositionToNative(const QPoint &pos, const QPlatformScreen *platformScreen) +diff --git a/qtbase/src/gui/kernel/qkeysequence.cpp b/qtbase/src/gui/kernel/qkeysequence.cpp +index a75b8ef920..4f2d294739 100644 +--- a/qtbase/src/gui/kernel/qkeysequence.cpp ++++ b/qtbase/src/gui/kernel/qkeysequence.cpp +@@ -701,6 +701,10 @@ static const struct { + { Qt::Key_TouchpadToggle, QT_TRANSLATE_NOOP("QShortcut", "Touchpad Toggle") }, + { Qt::Key_TouchpadOn, QT_TRANSLATE_NOOP("QShortcut", "Touchpad On") }, + { Qt::Key_TouchpadOff, QT_TRANSLATE_NOOP("QShortcut", "Touchpad Off") }, ++ { Qt::Key_Shift, QT_TRANSLATE_NOOP("QShortcut", "Shift") }, ++ { Qt::Key_Control, QT_TRANSLATE_NOOP("QShortcut", "Control") }, ++ { Qt::Key_Alt, QT_TRANSLATE_NOOP("QShortcut", "Alt") }, ++ { Qt::Key_Meta, QT_TRANSLATE_NOOP("QShortcut", "Meta") }, + + }; + static Q_CONSTEXPR int numKeyNames = sizeof keyname / sizeof *keyname; +diff --git a/qtbase/src/gui/kernel/qplatformservices.cpp b/qtbase/src/gui/kernel/qplatformservices.cpp +index fdc6a6c4aa..ac47f98c5d 100644 +--- a/qtbase/src/gui/kernel/qplatformservices.cpp ++++ b/qtbase/src/gui/kernel/qplatformservices.cpp +@@ -55,6 +55,19 @@ QT_BEGIN_NAMESPACE + \brief The QPlatformServices provides the backend for desktop-related functionality. + */ + ++/*! ++ \enum QPlatformServices::Capability ++ ++ Capabilities are used to determine a specific platform service's availability. ++ ++ \value ColorPickingFromScreen The platform natively supports color picking from screen. ++ This capability indicates that the platform supports "opaque" color picking, where the ++ platform implements a complete user experience for color picking and outputs a color. ++ This is in contrast to the application implementing the color picking user experience ++ (taking care of showing a cross hair, instructing the platform integration to obtain ++ the color at a given pixel, etc.). The related service function is pickColor(). ++ */ ++ + QPlatformServices::QPlatformServices() + { } + +@@ -85,5 +98,16 @@ QByteArray QPlatformServices::desktopEnvironment() const + return QByteArray("UNKNOWN"); + } + ++QPlatformServiceColorPicker *QPlatformServices::colorPicker(QWindow *parent) ++{ ++ Q_UNUSED(parent); ++ return nullptr; ++} ++ ++bool QPlatformServices::hasCapability(Capability capability) const ++{ ++ Q_UNUSED(capability) ++ return false; ++} + + QT_END_NAMESPACE +diff --git a/qtbase/src/gui/kernel/qplatformservices.h b/qtbase/src/gui/kernel/qplatformservices.h +index 5de96cfa7d..a8b2a4ce71 100644 +--- a/qtbase/src/gui/kernel/qplatformservices.h ++++ b/qtbase/src/gui/kernel/qplatformservices.h +@@ -50,16 +50,32 @@ + // + + #include ++#include + + QT_BEGIN_NAMESPACE + + class QUrl; ++class QWindow; ++ ++class Q_GUI_EXPORT QPlatformServiceColorPicker : public QObject ++{ ++ Q_OBJECT ++public: ++ using QObject::QObject; ++ virtual void pickColor() = 0; ++Q_SIGNALS: ++ void colorPicked(const QColor &color); ++}; + + class Q_GUI_EXPORT QPlatformServices + { + public: + Q_DISABLE_COPY_MOVE(QPlatformServices) + ++ enum Capability { ++ ColorPicking, ++ }; ++ + QPlatformServices(); + virtual ~QPlatformServices() { } + +@@ -67,6 +83,10 @@ public: + virtual bool openDocument(const QUrl &url); + + virtual QByteArray desktopEnvironment() const; ++ ++ virtual bool hasCapability(Capability capability) const; ++ ++ virtual QPlatformServiceColorPicker *colorPicker(QWindow *parent = nullptr); + }; + + QT_END_NAMESPACE +diff --git a/qtbase/src/gui/kernel/qplatformtheme.cpp b/qtbase/src/gui/kernel/qplatformtheme.cpp +index 71521c0339..2325873245 100644 +--- a/qtbase/src/gui/kernel/qplatformtheme.cpp ++++ b/qtbase/src/gui/kernel/qplatformtheme.cpp +@@ -163,6 +163,8 @@ QT_BEGIN_NAMESPACE + + \value ShowShortcutsInContextMenus (bool) Whether to display shortcut key sequences in context menus. + ++ \value ButtonPressKeys (QList) A list of keys that can be used to press buttons via keyboard input. ++ + \sa themeHint(), QStyle::pixelMetric() + */ + +@@ -563,6 +565,8 @@ QVariant QPlatformTheme::defaultThemeHint(ThemeHint hint) + } + case MouseQuickSelectionThreshold: + return QVariant(10); ++ case ButtonPressKeys: ++ return QVariant::fromValue(QList({ Qt::Key_Space, Qt::Key_Select })); + } + return QVariant(); + } +diff --git a/qtbase/src/gui/kernel/qplatformtheme.h b/qtbase/src/gui/kernel/qplatformtheme.h +index 3185fc4541..7e6c9d5740 100644 +--- a/qtbase/src/gui/kernel/qplatformtheme.h ++++ b/qtbase/src/gui/kernel/qplatformtheme.h +@@ -120,7 +120,8 @@ public: + TouchDoubleTapDistance, + ShowShortcutsInContextMenus, + IconFallbackSearchPaths, +- MouseQuickSelectionThreshold ++ MouseQuickSelectionThreshold, ++ ButtonPressKeys + }; + + enum DialogType { +diff --git a/qtbase/src/gui/kernel/qscreen.cpp b/qtbase/src/gui/kernel/qscreen.cpp +index 8e0eb35116..5d172a58dd 100644 +--- a/qtbase/src/gui/kernel/qscreen.cpp ++++ b/qtbase/src/gui/kernel/qscreen.cpp +@@ -77,6 +77,12 @@ QScreen::QScreen(QPlatformScreen *screen) + d->setPlatformScreen(screen); + } + ++void QScreenPrivate::updateLogicalDpi() ++{ ++ logicalDpi = QPlatformScreen::overrideDpi(platformScreen->logicalDpi()); ++ updateGeometriesWithSignals(); // updates geometries based on scale factor ++} ++ + void QScreenPrivate::updateGeometriesWithSignals() + { + const QRect oldGeometry = geometry; +diff --git a/qtbase/src/gui/kernel/qscreen_p.h b/qtbase/src/gui/kernel/qscreen_p.h +index 7da542c25e..e50fc3190b 100644 +--- a/qtbase/src/gui/kernel/qscreen_p.h ++++ b/qtbase/src/gui/kernel/qscreen_p.h +@@ -70,6 +70,7 @@ public: + geometry = platformScreen->deviceIndependentGeometry(); + availableGeometry = QHighDpi::fromNative(platformScreen->availableGeometry(), QHighDpiScaling::factor(platformScreen), geometry.topLeft()); + } ++ void updateLogicalDpi(); + + void updatePrimaryOrientation(); + void updateGeometriesWithSignals(); +diff --git a/qtbase/src/gui/painting/qblendfunctions_p.h b/qtbase/src/gui/painting/qblendfunctions_p.h +index 080da98ec4..6997d62b3c 100644 +--- a/qtbase/src/gui/painting/qblendfunctions_p.h ++++ b/qtbase/src/gui/painting/qblendfunctions_p.h +@@ -246,25 +246,32 @@ void qt_transform_image_rasterize(DestT *destPixels, int dbpl, + int dudx, int dvdx, int dudy, int dvdy, int u0, int v0, + Blender blender) + { +- int fromY = qMax(qRound(topY), clip.top()); +- int toY = qMin(qRound(bottomY), clip.top() + clip.height()); ++ qint64 fromY = qMax(qRound(topY), clip.top()); ++ qint64 toY = qMin(qRound(bottomY), clip.top() + clip.height()); + if (fromY >= toY) + return; + + qreal leftSlope = (bottomLeft.x - topLeft.x) / (bottomLeft.y - topLeft.y); + qreal rightSlope = (bottomRight.x - topRight.x) / (bottomRight.y - topRight.y); +- int dx_l = int(leftSlope * 0x10000); +- int dx_r = int(rightSlope * 0x10000); +- int x_l = int((topLeft.x + (qreal(0.5) + fromY - topLeft.y) * leftSlope + qreal(0.5)) * 0x10000); +- int x_r = int((topRight.x + (qreal(0.5) + fromY - topRight.y) * rightSlope + qreal(0.5)) * 0x10000); +- +- int fromX, toX, x1, x2, u, v, i, ii; ++ qint64 dx_l = qint64(leftSlope * 0x10000); ++ qint64 dx_r = qint64(rightSlope * 0x10000); ++ qint64 x_l = qint64((topLeft.x + (qreal(0.5) + fromY - topLeft.y) * leftSlope + qreal(0.5)) * 0x10000); ++ qint64 x_r = qint64((topRight.x + (qreal(0.5) + fromY - topRight.y) * rightSlope + qreal(0.5)) * 0x10000); ++ ++ qint64 sourceRectTop = qint64(sourceRect.top()); ++ qint64 sourceRectLeft = qint64(sourceRect.left()); ++ qint64 sourceRectWidth = qint64(sourceRect.width()); ++ qint64 sourceRectHeight = qint64(sourceRect.height()); ++ qint64 clipLeft = qint64(clip.left()); ++ qint64 clipWidth = qint64(clip.width()); ++ ++ qint64 fromX, toX, x1, x2, u, v, i, ii; + DestT *line; +- for (int y = fromY; y < toY; ++y) { ++ for (qint64 y = fromY; y < toY; ++y) { + line = reinterpret_cast(reinterpret_cast(destPixels) + y * dbpl); + +- fromX = qMax(x_l >> 16, clip.left()); +- toX = qMin(x_r >> 16, clip.left() + clip.width()); ++ fromX = qMax(x_l >> 16, clipLeft); ++ toX = qMin(x_r >> 16, clipLeft + clipWidth); + if (fromX < toX) { + // Because of rounding, we can get source coordinates outside the source image. + // Clamp these coordinates to the source rect to avoid segmentation fault and +@@ -275,10 +282,10 @@ void qt_transform_image_rasterize(DestT *destPixels, int dbpl, + u = x1 * dudx + y * dudy + u0; + v = x1 * dvdx + y * dvdy + v0; + for (; x1 < toX; ++x1) { +- int uu = u >> 16; +- int vv = v >> 16; +- if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width() +- && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) { ++ qint64 uu = u >> 16; ++ qint64 vv = v >> 16; ++ if (uu >= sourceRectLeft && uu < sourceRectLeft + sourceRectWidth ++ && vv >= sourceRectTop && vv < sourceRectTop + sourceRectHeight) { + break; + } + u += dudx; +@@ -290,10 +297,10 @@ void qt_transform_image_rasterize(DestT *destPixels, int dbpl, + u = (x2 - 1) * dudx + y * dudy + u0; + v = (x2 - 1) * dvdx + y * dvdy + v0; + for (; x2 > x1; --x2) { +- int uu = u >> 16; +- int vv = v >> 16; +- if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width() +- && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) { ++ qint64 uu = u >> 16; ++ qint64 vv = v >> 16; ++ if (uu >= sourceRectLeft && uu < sourceRectLeft + sourceRectWidth ++ && vv >= sourceRectTop && vv < sourceRectTop + sourceRectHeight) { + break; + } + u -= dudx; +@@ -308,8 +315,8 @@ void qt_transform_image_rasterize(DestT *destPixels, int dbpl, + // Beginning of the scan line, with per-pixel checks. + i = x1 - fromX; + while (i) { +- int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1); +- int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1); ++ qint64 uu = qBound(sourceRectLeft, u >> 16, sourceRectLeft + sourceRectWidth - 1); ++ qint64 vv = qBound(sourceRectTop, v >> 16, sourceRectTop + sourceRectHeight - 1); + blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + vv * sbpl)[uu]); + u += dudx; + v += dvdx; +@@ -348,8 +355,8 @@ void qt_transform_image_rasterize(DestT *destPixels, int dbpl, + // End of the scan line, with per-pixel checks. + i = toX - x2; + while (i) { +- int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1); +- int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1); ++ qint64 uu = qBound(sourceRectLeft, u >> 16, sourceRectLeft + sourceRectWidth - 1); ++ qint64 vv = qBound(sourceRectTop, v >> 16, sourceRectTop + sourceRectHeight - 1); + blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + vv * sbpl)[uu]); + u += dudx; + v += dvdx; +diff --git a/qtbase/src/gui/painting/qcolortrclut_p.h b/qtbase/src/gui/painting/qcolortrclut_p.h +index 76a6a60803..24fd522e6c 100644 +--- a/qtbase/src/gui/painting/qcolortrclut_p.h ++++ b/qtbase/src/gui/painting/qcolortrclut_p.h +@@ -118,6 +118,7 @@ public: + return QRgba64::fromRgba64(r, g, b, qAlpha(rgb32) * 257); + #endif + } ++ QRgba64 toLinear64(QRgba64) const = delete; + + QRgb toLinear(QRgb rgb32) const + { +diff --git a/qtbase/src/gui/painting/qdrawhelper.cpp b/qtbase/src/gui/painting/qdrawhelper.cpp +index a61793508a..5ba2d277b7 100644 +--- a/qtbase/src/gui/painting/qdrawhelper.cpp ++++ b/qtbase/src/gui/painting/qdrawhelper.cpp +@@ -6091,7 +6091,7 @@ static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba + static inline void rgbBlendPixel(QRgba64 &dst, int coverage, QRgba64 slinear, const QColorTrcLut *colorProfile) + { + // Do a gammacorrected RGB alphablend... +- const QRgba64 dlinear = colorProfile ? colorProfile->toLinear64(dst) : dst; ++ const QRgba64 dlinear = colorProfile ? colorProfile->toLinear(dst) : dst; + + QRgba64 blend = rgbBlend(dlinear, slinear, coverage); + +diff --git a/qtbase/src/gui/painting/qpaintengine_raster.cpp b/qtbase/src/gui/painting/qpaintengine_raster.cpp +index 283923de52..f08eb9cbee 100644 +--- a/qtbase/src/gui/painting/qpaintengine_raster.cpp ++++ b/qtbase/src/gui/painting/qpaintengine_raster.cpp +@@ -560,31 +560,6 @@ void QRasterPaintEngine::updateMatrix(const QTransform &matrix) + QRasterPaintEngineState *s = state(); + // FALCON: get rid of this line, see drawImage call below. + s->matrix = matrix; +- QTransform::TransformationType txop = s->matrix.type(); +- +- switch (txop) { +- +- case QTransform::TxNone: +- s->flags.int_xform = true; +- break; +- +- case QTransform::TxTranslate: +- s->flags.int_xform = qreal(int(s->matrix.dx())) == s->matrix.dx() +- && qreal(int(s->matrix.dy())) == s->matrix.dy(); +- break; +- +- case QTransform::TxScale: +- s->flags.int_xform = qreal(int(s->matrix.dx())) == s->matrix.dx() +- && qreal(int(s->matrix.dy())) == s->matrix.dy() +- && qreal(int(s->matrix.m11())) == s->matrix.m11() +- && qreal(int(s->matrix.m22())) == s->matrix.m22(); +- break; +- +- default: // shear / perspective... +- s->flags.int_xform = false; +- break; +- } +- + s->flags.tx_noshear = qt_scaleForTransform(s->matrix, &s->txscale); + + ensureOutlineMapper(); +@@ -617,7 +592,6 @@ QRasterPaintEngineState::QRasterPaintEngineState() + flags.bilinear = false; + flags.legacy_rounding = false; + flags.fast_text = true; +- flags.int_xform = true; + flags.tx_noshear = true; + flags.fast_images = true; + +@@ -1793,7 +1767,7 @@ void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush) + QRectF cpRect = path.controlPointRect(); + const QRectF pathDeviceRect = s->matrix.mapRect(cpRect); + // Skip paths that by conservative estimates are completely outside the paint device. +- if (!pathDeviceRect.intersects(QRectF(d->deviceRect))) ++ if (!pathDeviceRect.intersects(QRectF(d->deviceRect)) || !pathDeviceRect.isValid()) + return; + + ProcessSpans blend = d->getBrushFunc(pathDeviceRect, &s->brushData); +diff --git a/qtbase/src/gui/painting/qpaintengine_raster_p.h b/qtbase/src/gui/painting/qpaintengine_raster_p.h +index 089aadc3f7..bf7363d5aa 100644 +--- a/qtbase/src/gui/painting/qpaintengine_raster_p.h ++++ b/qtbase/src/gui/painting/qpaintengine_raster_p.h +@@ -111,7 +111,6 @@ public: + uint bilinear : 1; + uint legacy_rounding : 1; + uint fast_text : 1; +- uint int_xform : 1; + uint tx_noshear : 1; + uint fast_images : 1; + }; +diff --git a/qtbase/src/gui/painting/qpainterpath.cpp b/qtbase/src/gui/painting/qpainterpath.cpp +index f9544a3241..d80fafeaf1 100644 +--- a/qtbase/src/gui/painting/qpainterpath.cpp ++++ b/qtbase/src/gui/painting/qpainterpath.cpp +@@ -1253,7 +1253,7 @@ void QPainterPath::addText(const QPointF &point, const QFont &f, const QString & + + if (si.analysis.flags < QScriptAnalysis::TabOrObject) { + QGlyphLayout glyphs = eng->shapedGlyphs(&si); +- QFontEngine *fe = f.d->engineForScript(si.analysis.script); ++ QFontEngine *fe = eng->fontEngine(si); + Q_ASSERT(fe); + fe->addOutlineToPath(x, y, glyphs, this, + si.analysis.bidiLevel % 2 +diff --git a/qtbase/src/gui/painting/qpathclipper_p.h b/qtbase/src/gui/painting/qpathclipper_p.h +index 9444a87b71..18f64c5e8c 100644 +--- a/qtbase/src/gui/painting/qpathclipper_p.h ++++ b/qtbase/src/gui/painting/qpathclipper_p.h +@@ -156,7 +156,7 @@ public: + int vertex(Direction direction) const; + + private: +- int m_next[2][2]; ++ int m_next[2][2] = { { -1, -1 }, { -1, -1 } }; + }; + + class QPathSegments +@@ -296,10 +296,6 @@ inline QPathEdge::QPathEdge(int a, int b) + , angle(0) + , invAngle(0) + { +- m_next[0][0] = -1; +- m_next[1][0] = -1; +- m_next[0][0] = -1; +- m_next[1][0] = -1; + } + + inline int QPathEdge::next(Traversal traversal, Direction direction) const +diff --git a/qtbase/src/gui/painting/qpdf.cpp b/qtbase/src/gui/painting/qpdf.cpp +index 3066744f1b..2c8d3c3b53 100644 +--- a/qtbase/src/gui/painting/qpdf.cpp ++++ b/qtbase/src/gui/painting/qpdf.cpp +@@ -2760,6 +2760,8 @@ int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor, + return gradientBrush(brush, matrix, gStateObject); + } + ++ matrix = brush.transform() * matrix; ++ + if ((!brush.isOpaque() && brush.style() < Qt::LinearGradientPattern) || opacity != 1.0) + *gStateObject = addConstantAlphaObject(qRound(brush.color().alpha() * opacity), + qRound(pen.color().alpha() * opacity)); +diff --git a/qtbase/src/gui/painting/qstroker.cpp b/qtbase/src/gui/painting/qstroker.cpp +index cb5d395e80..3b6357a893 100644 +--- a/qtbase/src/gui/painting/qstroker.cpp ++++ b/qtbase/src/gui/painting/qstroker.cpp +@@ -1182,6 +1182,7 @@ void QDashStroker::processCurrentSubpath() + // Check if the entire line should be clipped away or simplified + bool clipIt = clipping && !lineIntersectsRect(prev, e, clip_tl, clip_br); + bool skipDashing = elen * invSumLength > repetitionLimit(); ++ int maxDashes = dashCount; + if (skipDashing || clipIt) { + // Cut away full dash sequences. + elen -= std::floor(elen * invSumLength) * sumLength; +@@ -1196,7 +1197,7 @@ void QDashStroker::processCurrentSubpath() + pos = estop; // move pos to next path element + done = true; + } else { // Dash is on this line +- pos = dpos + estart; ++ pos = --maxDashes > 0 ? dpos + estart : estop; + done = pos >= estop; + if (++idash >= dashCount) + idash = 0; +diff --git a/qtbase/src/gui/painting/qt_attribution.json b/qtbase/src/gui/painting/qt_attribution.json +index 7b16e8c211..0e87d30aa2 100644 +--- a/qtbase/src/gui/painting/qt_attribution.json ++++ b/qtbase/src/gui/painting/qt_attribution.json +@@ -10,7 +10,7 @@ + "Homepage": "http://www.freetype.org", + "License": "Freetype Project License or GNU General Public License v2.0 only", + "LicenseId": "FTL or GPL-2.0", +- "LicenseFile": "../../3rdparty/freetype/docs/LICENSE.TXT", ++ "LicenseFile": "../../3rdparty/freetype/LICENSE.TXT", + "Copyright": "Copyright 2000-2016 by David Turner, Robert Wilhelm, and Werner Lemberg." + }, + { +diff --git a/qtbase/src/gui/rhi/qshader_p_p.h b/qtbase/src/gui/rhi/qshader_p_p.h +index ec9d25971f..4a5a7a6d51 100644 +--- a/qtbase/src/gui/rhi/qshader_p_p.h ++++ b/qtbase/src/gui/rhi/qshader_p_p.h +@@ -68,13 +68,13 @@ struct Q_GUI_EXPORT QShaderPrivate + { + } + +- QShaderPrivate(const QShaderPrivate *other) ++ QShaderPrivate(const QShaderPrivate &other) + : ref(1), +- qsbVersion(other->qsbVersion), +- stage(other->stage), +- desc(other->desc), +- shaders(other->shaders), +- bindings(other->bindings) ++ qsbVersion(other.qsbVersion), ++ stage(other.stage), ++ desc(other.desc), ++ shaders(other.shaders), ++ bindings(other.bindings) + { + } + +diff --git a/qtbase/src/gui/rhi/qshaderdescription_p_p.h b/qtbase/src/gui/rhi/qshaderdescription_p_p.h +index ec2b0b6b4c..3da33a8a2b 100644 +--- a/qtbase/src/gui/rhi/qshaderdescription_p_p.h ++++ b/qtbase/src/gui/rhi/qshaderdescription_p_p.h +@@ -63,16 +63,16 @@ struct Q_GUI_EXPORT QShaderDescriptionPrivate + localSize[0] = localSize[1] = localSize[2] = 0; + } + +- QShaderDescriptionPrivate(const QShaderDescriptionPrivate *other) ++ QShaderDescriptionPrivate(const QShaderDescriptionPrivate &other) + : ref(1), +- inVars(other->inVars), +- outVars(other->outVars), +- uniformBlocks(other->uniformBlocks), +- pushConstantBlocks(other->pushConstantBlocks), +- storageBlocks(other->storageBlocks), +- combinedImageSamplers(other->combinedImageSamplers), +- storageImages(other->storageImages), +- localSize(other->localSize) ++ inVars(other.inVars), ++ outVars(other.outVars), ++ uniformBlocks(other.uniformBlocks), ++ pushConstantBlocks(other.pushConstantBlocks), ++ storageBlocks(other.storageBlocks), ++ combinedImageSamplers(other.combinedImageSamplers), ++ storageImages(other.storageImages), ++ localSize(other.localSize) + { + } + +diff --git a/qtbase/src/gui/text/qfontdatabase.cpp b/qtbase/src/gui/text/qfontdatabase.cpp +index a657a8c516..4fc0100958 100644 +--- a/qtbase/src/gui/text/qfontdatabase.cpp ++++ b/qtbase/src/gui/text/qfontdatabase.cpp +@@ -983,7 +983,7 @@ QFontEngine *loadSingleEngine(int script, + if (style->key.stretch != 0 && request.stretch != 0 + && (request.styleName.isEmpty() || request.styleName != style->styleName)) { + def.stretch = (request.stretch * 100 + style->key.stretch / 2) / style->key.stretch; +- } else { ++ } else if (request.stretch == QFont::AnyStretch) { + def.stretch = 100; + } + +diff --git a/qtbase/src/gui/text/qtextdocumentlayout.cpp b/qtbase/src/gui/text/qtextdocumentlayout.cpp +index f3e6ea2100..72267e9380 100644 +--- a/qtbase/src/gui/text/qtextdocumentlayout.cpp ++++ b/qtbase/src/gui/text/qtextdocumentlayout.cpp +@@ -2123,7 +2123,7 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p + { + Q_Q(const QTextDocumentLayout); + const QTextBlockFormat blockFormat = bl.blockFormat(); +- const QTextCharFormat charFormat = QTextCursor(bl).charFormat(); ++ const QTextCharFormat charFormat = bl.charFormat(); + QFont font(charFormat.font()); + if (q->paintDevice()) + font = QFont(font, q->paintDevice()); +diff --git a/qtbase/src/gui/text/qtextengine.cpp b/qtbase/src/gui/text/qtextengine.cpp +index ce4abac472..a6c66e5d2d 100644 +--- a/qtbase/src/gui/text/qtextengine.cpp ++++ b/qtbase/src/gui/text/qtextengine.cpp +@@ -1,6 +1,6 @@ + /**************************************************************************** + ** +-** Copyright (C) 2016 The Qt Company Ltd. ++** Copyright (C) 2021 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the QtGui module of the Qt Toolkit. +@@ -1565,6 +1565,12 @@ void QTextEngine::shapeText(int item) const + // Overwrite with 0 token to indicate failure + QGlyphLayout g = availableGlyphs(&si); + g.glyphs[0] = 0; ++ g.attributes[0].clusterStart = true; ++ ++ ushort *log_clusters = logClusters(&si); ++ for (int i = 0; i < itemLength; ++i) ++ log_clusters[i] = 0; ++ + return; + } + +diff --git a/qtbase/src/gui/util/qdesktopservices.cpp b/qtbase/src/gui/util/qdesktopservices.cpp +index fbb63a9408..4d5fafaaa7 100644 +--- a/qtbase/src/gui/util/qdesktopservices.cpp ++++ b/qtbase/src/gui/util/qdesktopservices.cpp +@@ -54,6 +54,8 @@ + #include + #include + ++#include ++ + QT_BEGIN_NAMESPACE + + class QOpenUrlHandlerRegistry : public QObject +@@ -81,6 +83,7 @@ Q_GLOBAL_STATIC(QOpenUrlHandlerRegistry, handlerRegistry) + + void QOpenUrlHandlerRegistry::handlerDestroyed(QObject *handler) + { ++ const auto lock = qt_scoped_lock(mutex); + HandlerHash::Iterator it = handlers.begin(); + while (it != handlers.end()) { + if (it->receiver == handler) { +@@ -294,7 +297,8 @@ void QDesktopServices::setUrlHandler(const QString &scheme, QObject *receiver, c + h.name = method; + registry->handlers.insert(scheme.toLower(), h); + QObject::connect(receiver, SIGNAL(destroyed(QObject*)), +- registry, SLOT(handlerDestroyed(QObject*))); ++ registry, SLOT(handlerDestroyed(QObject*)), ++ Qt::DirectConnection); + } + + /*! +diff --git a/qtbase/src/gui/util/qpkmhandler.cpp b/qtbase/src/gui/util/qpkmhandler.cpp +index e0c3b75efe..3414f9d8ba 100644 +--- a/qtbase/src/gui/util/qpkmhandler.cpp ++++ b/qtbase/src/gui/util/qpkmhandler.cpp +@@ -57,7 +57,7 @@ struct PkmType + quint32 bytesPerBlock; + }; + +-static PkmType typeMap[5] = { ++static constexpr PkmType typeMap[5] = { + { 0x8D64, 8 }, // GL_ETC1_RGB8_OES + { 0x9274, 8 }, // GL_COMPRESSED_RGB8_ETC2 + { 0, 0 }, // unused (obsolete) +diff --git a/qtbase/src/network/access/qnetworkreplyfileimpl.cpp b/qtbase/src/network/access/qnetworkreplyfileimpl.cpp +index b6be93147a..6e69b4c4d3 100644 +--- a/qtbase/src/network/access/qnetworkreplyfileimpl.cpp ++++ b/qtbase/src/network/access/qnetworkreplyfileimpl.cpp +@@ -89,9 +89,10 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QNetworkAccessManager *manager, con + // we handle only local files + QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Request for opening non-local file %1").arg(url.toString()); + setError(QNetworkReply::ProtocolInvalidOperationError, msg); ++ setFinished(true); // We're finished, will emit finished() after ctor is done. + QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection, + Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolInvalidOperationError)); +- fileOpenFinished(false); ++ QMetaObject::invokeMethod(this, [this](){ fileOpenFinished(false); }, Qt::QueuedConnection); + return; + } + #endif +diff --git a/qtbase/src/network/access/qnetworkreplyimpl.cpp b/qtbase/src/network/access/qnetworkreplyimpl.cpp +index bcdf6ee2f1..3b6deb82bd 100644 +--- a/qtbase/src/network/access/qnetworkreplyimpl.cpp ++++ b/qtbase/src/network/access/qnetworkreplyimpl.cpp +@@ -680,7 +680,7 @@ void QNetworkReplyImplPrivate::appendDownstreamData(QIODevice *data) + // read until EOF from data + if (Q_UNLIKELY(copyDevice)) { + qCritical("QNetworkReplyImpl: copy from QIODevice already in progress -- " +- "backend probly needs to be fixed"); ++ "backend probably needs to be fixed"); + return; + } + +diff --git a/qtbase/src/network/kernel/qauthenticator.cpp b/qtbase/src/network/kernel/qauthenticator.cpp +index d9fe7bc47b..ccd04b294a 100644 +--- a/qtbase/src/network/kernel/qauthenticator.cpp ++++ b/qtbase/src/network/kernel/qauthenticator.cpp +@@ -50,6 +50,7 @@ + #include + #include + #include ++#include "private/qsystemlibrary_p.h" + + #ifdef Q_OS_WIN + #include +@@ -1563,7 +1564,7 @@ static bool q_SSPI_library_load() + + // Initialize security interface + if (pSecurityFunctionTable == nullptr) { +- securityDLLHandle = LoadLibrary(L"secur32.dll"); ++ securityDLLHandle = QSystemLibrary::load(L"secur32"); + if (securityDLLHandle != nullptr) { + INIT_SECURITY_INTERFACE pInitSecurityInterface = + reinterpret_cast( +diff --git a/qtbase/src/network/kernel/qhostinfo_unix.cpp b/qtbase/src/network/kernel/qhostinfo_unix.cpp +index 9b0a2ee669..73679c9ef1 100644 +--- a/qtbase/src/network/kernel/qhostinfo_unix.cpp ++++ b/qtbase/src/network/kernel/qhostinfo_unix.cpp +@@ -122,7 +122,6 @@ static QFunctionPointer resolveSymbol(QLibrary &lib, const char *sym) + + LibResolv::LibResolv() + { +- QLibrary lib; + #ifdef LIBRESOLV_SO + lib.setFileName(QStringLiteral(LIBRESOLV_SO)); + if (!lib.load()) +diff --git a/qtbase/src/network/socket/qsocks5socketengine.cpp b/qtbase/src/network/socket/qsocks5socketengine.cpp +index 3a046fd116..97fadca0b3 100644 +--- a/qtbase/src/network/socket/qsocks5socketengine.cpp ++++ b/qtbase/src/network/socket/qsocks5socketengine.cpp +@@ -1296,7 +1296,7 @@ void QSocks5SocketEnginePrivate::_q_udpSocketReadNotification() + int pos = 0; + const char *buf = inBuf.constData(); + if (inBuf.size() < 4) { +- QSOCKS5_D_DEBUG << "bugus udp data, discarding"; ++ QSOCKS5_D_DEBUG << "bogus udp data, discarding"; + return; + } + QSocks5RevivedDatagram datagram; +diff --git a/qtbase/src/network/ssl/qsslcontext_openssl.cpp b/qtbase/src/network/ssl/qsslcontext_openssl.cpp +index c9f202f573..c992da9d8e 100644 +--- a/qtbase/src/network/ssl/qsslcontext_openssl.cpp ++++ b/qtbase/src/network/ssl/qsslcontext_openssl.cpp +@@ -409,7 +409,7 @@ init_context: + break; + case QSsl::DtlsV1_0OrLater: + minVersion = DTLS1_VERSION; +- maxVersion = DTLS_MAX_VERSION; ++ maxVersion = 0; + break; + case QSsl::DtlsV1_2: + minVersion = DTLS1_2_VERSION; +@@ -417,7 +417,7 @@ init_context: + break; + case QSsl::DtlsV1_2OrLater: + minVersion = DTLS1_2_VERSION; +- maxVersion = DTLS_MAX_VERSION; ++ maxVersion = 0; + break; + case QSsl::TlsV1_3OrLater: + #ifdef TLS1_3_VERSION +@@ -455,7 +455,7 @@ init_context: + } + + // Enable bug workarounds. +- long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions); ++ qssloptions options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions); + q_SSL_CTX_set_options(sslContext->ctx, options); + + // Tell OpenSSL to release memory early +diff --git a/qtbase/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp b/qtbase/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp +index aaf8741130..b58935372c 100644 +--- a/qtbase/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp ++++ b/qtbase/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp +@@ -59,57 +59,6 @@ + + QT_BEGIN_NAMESPACE + +-#ifdef OPENSSL_NO_DEPRECATED_3_0 +- +-static int q_DH_check(DH *dh, int *status) +-{ +- // DH_check was first deprecated in OpenSSL 3.0.0, as low-level +- // API; the EVP_PKEY family of functions was advised as an alternative. +- // As of now EVP_PKEY_params_check ends up calling ... DH_check, +- // which is good enough. +- +- Q_ASSERT(dh); +- Q_ASSERT(status); +- +- EVP_PKEY *key = q_EVP_PKEY_new(); +- if (!key) { +- qCWarning(lcSsl, "EVP_PKEY_new failed"); +- QSslSocketBackendPrivate::logAndClearErrorQueue(); +- return 0; +- } +- const auto keyDeleter = qScopeGuard([key](){ +- q_EVP_PKEY_free(key); +- }); +- if (!q_EVP_PKEY_set1_DH(key, dh)) { +- qCWarning(lcSsl, "EVP_PKEY_set1_DH failed"); +- QSslSocketBackendPrivate::logAndClearErrorQueue(); +- return 0; +- } +- +- EVP_PKEY_CTX *keyCtx = q_EVP_PKEY_CTX_new(key, nullptr); +- if (!keyCtx) { +- qCWarning(lcSsl, "EVP_PKEY_CTX_new failed"); +- QSslSocketBackendPrivate::logAndClearErrorQueue(); +- return 0; +- } +- const auto ctxDeleter = qScopeGuard([keyCtx]{ +- q_EVP_PKEY_CTX_free(keyCtx); +- }); +- +- const int result = q_EVP_PKEY_param_check(keyCtx); +- QSslSocketBackendPrivate::logAndClearErrorQueue(); +- // Note: unlike DH_check, we cannot obtain the 'status', +- // if the 'result' is 0 (actually the result is 1 only +- // if this 'status' was 0). We could probably check the +- // errors from the error queue, but it's not needed anyway +- // - see the 'isSafeDH' below, how it returns immediately +- // on 0. +- Q_UNUSED(status) +- +- return result; +-} +-#endif // OPENSSL_NO_DEPRECATED_3_0 +- + static bool isSafeDH(DH *dh) + { + int status = 0; +diff --git a/qtbase/src/network/ssl/qsslsocket_openssl.cpp b/qtbase/src/network/ssl/qsslsocket_openssl.cpp +index 37fad2a68f..8f6858c867 100644 +--- a/qtbase/src/network/ssl/qsslsocket_openssl.cpp ++++ b/qtbase/src/network/ssl/qsslsocket_openssl.cpp +@@ -550,9 +550,9 @@ static void q_loadCiphersForConnection(SSL *connection, QList &ciphe + // Defined in qsslsocket.cpp + void q_setDefaultDtlsCiphers(const QList &ciphers); + +-long QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions) ++qssloptions QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions) + { +- long options; ++ qssloptions options; + if (protocol == QSsl::TlsV1SslV3) + options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3; + else if (protocol == QSsl::SecureProtocols) +diff --git a/qtbase/src/network/ssl/qsslsocket_openssl_p.h b/qtbase/src/network/ssl/qsslsocket_openssl_p.h +index 4103de23e8..5547589256 100644 +--- a/qtbase/src/network/ssl/qsslsocket_openssl_p.h ++++ b/qtbase/src/network/ssl/qsslsocket_openssl_p.h +@@ -107,6 +107,12 @@ + + QT_BEGIN_NAMESPACE + ++#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 ++typedef uint64_t qssloptions; ++#else ++typedef unsigned long qssloptions; ++#endif ++ + struct QSslErrorEntry { + int code; + int depth; +@@ -171,7 +177,7 @@ public: + QVector ocspErrors; + QByteArray ocspResponseDer; + +- Q_AUTOTEST_EXPORT static long setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions); ++ Q_AUTOTEST_EXPORT static qssloptions setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions); + static QSslCipher QSslCipher_from_SSL_CIPHER(const SSL_CIPHER *cipher); + static QList STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509); + static QList verify(const QList &certificateChain, const QString &hostName); +diff --git a/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp b/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp +index e53fb279f0..459ccd0b19 100644 +--- a/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp ++++ b/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp +@@ -148,7 +148,6 @@ DEFINEFUNC(int, EVP_PKEY_up_ref, EVP_PKEY *a, a, return 0, return) + DEFINEFUNC2(EVP_PKEY_CTX *, EVP_PKEY_CTX_new, EVP_PKEY *pkey, pkey, ENGINE *e, e, return nullptr, return) + DEFINEFUNC(int, EVP_PKEY_param_check, EVP_PKEY_CTX *ctx, ctx, return 0, return) + DEFINEFUNC(void, EVP_PKEY_CTX_free, EVP_PKEY_CTX *ctx, ctx, return, return) +-DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return) + DEFINEFUNC(int, RSA_bits, RSA *a, a, return 0, return) + DEFINEFUNC(int, DSA_bits, DSA *a, a, return 0, return) + DEFINEFUNC(int, OPENSSL_sk_num, OPENSSL_STACK *a, a, return -1, return) +@@ -158,7 +157,7 @@ DEFINEFUNC2(void, OPENSSL_sk_push, OPENSSL_STACK *a, a, void *b, b, return, DUMM + DEFINEFUNC(void, OPENSSL_sk_free, OPENSSL_STACK *a, a, return, DUMMYARG) + DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return nullptr, return) + DEFINEFUNC(int, SSL_session_reused, SSL *a, a, return 0, return) +-DEFINEFUNC2(unsigned long, SSL_CTX_set_options, SSL_CTX *ctx, ctx, unsigned long op, op, return 0, return) ++DEFINEFUNC2(qssloptions, SSL_CTX_set_options, SSL_CTX *ctx, ctx, qssloptions op, op, return 0, return) + DEFINEFUNC(int, SSL_CTX_get_security_level, const SSL_CTX *ctx, ctx, return -1, return) + DEFINEFUNC2(void, SSL_CTX_set_security_level, SSL_CTX *ctx, ctx, int level, level, return, return) + #ifdef TLS1_3_VERSION +@@ -371,7 +370,15 @@ DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return nullptr + DEFINEFUNC(int, SSL_version, const SSL *a, a, return 0, return) + DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return) + DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return nullptr, return) ++ ++#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 ++DEFINEFUNC(X509 *, SSL_get1_peer_certificate, SSL *a, a, return nullptr, return) ++DEFINEFUNC(int, EVP_PKEY_get_base_id, const EVP_PKEY *pkey, pkey, return -1, return) ++#else + DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return nullptr, return) ++DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return) ++#endif // OPENSSL_VERSION_MAJOR >= 3 ++ + DEFINEFUNC(long, SSL_get_verify_result, const SSL *a, a, return -1, return) + DEFINEFUNC(SSL *, SSL_new, SSL_CTX *a, a, return nullptr, return) + DEFINEFUNC(SSL_CTX *, SSL_get_SSL_CTX, SSL *a, a, return nullptr, return) +@@ -492,9 +499,7 @@ DEFINEFUNC(DH *, DH_new, DUMMYARG, DUMMYARG, return nullptr, return) + DEFINEFUNC(void, DH_free, DH *dh, dh, return, DUMMYARG) + DEFINEFUNC3(DH *, d2i_DHparams, DH**a, a, const unsigned char **pp, pp, long length, length, return nullptr, return) + DEFINEFUNC2(int, i2d_DHparams, DH *a, a, unsigned char **p, p, return -1, return) +-#ifndef OPENSSL_NO_DEPRECATED_3_0 + DEFINEFUNC2(int, DH_check, DH *dh, dh, int *codes, codes, return 0, return) +-#endif // OPENSSL_NO_DEPRECATED_3_0 + DEFINEFUNC3(BIGNUM *, BN_bin2bn, const unsigned char *s, s, int len, len, BIGNUM *ret, ret, return nullptr, return) + + #ifndef OPENSSL_NO_EC +@@ -868,7 +873,6 @@ bool q_resolveOpenSslSymbols() + RESOLVEFUNC(EVP_PKEY_CTX_new) + RESOLVEFUNC(EVP_PKEY_param_check) + RESOLVEFUNC(EVP_PKEY_CTX_free) +- RESOLVEFUNC(EVP_PKEY_base_id) + RESOLVEFUNC(RSA_bits) + RESOLVEFUNC(OPENSSL_sk_new_null) + RESOLVEFUNC(OPENSSL_sk_push) +@@ -1107,7 +1111,15 @@ bool q_resolveOpenSslSymbols() + RESOLVEFUNC(SSL_version) + RESOLVEFUNC(SSL_get_error) + RESOLVEFUNC(SSL_get_peer_cert_chain) ++ ++#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 ++ RESOLVEFUNC(SSL_get1_peer_certificate) ++ RESOLVEFUNC(EVP_PKEY_get_base_id) ++#else + RESOLVEFUNC(SSL_get_peer_certificate) ++ RESOLVEFUNC(EVP_PKEY_base_id) ++#endif // OPENSSL_VERSION_MAJOR >= 3 ++ + RESOLVEFUNC(SSL_get_verify_result) + RESOLVEFUNC(SSL_new) + RESOLVEFUNC(SSL_get_SSL_CTX) +@@ -1206,9 +1218,7 @@ bool q_resolveOpenSslSymbols() + RESOLVEFUNC(DH_free) + RESOLVEFUNC(d2i_DHparams) + RESOLVEFUNC(i2d_DHparams) +-#ifndef OPENSSL_NO_DEPRECATED_3_0 + RESOLVEFUNC(DH_check) +-#endif // OPENSSL_NO_DEPRECATED_3_0 + RESOLVEFUNC(BN_bin2bn) + + #ifndef OPENSSL_NO_EC +diff --git a/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h b/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h +index 95e8897a3b..27aeffa18a 100644 +--- a/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h ++++ b/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h +@@ -237,7 +237,6 @@ Q_AUTOTEST_EXPORT int q_EVP_PKEY_up_ref(EVP_PKEY *a); + EVP_PKEY_CTX *q_EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e); + void q_EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); + int q_EVP_PKEY_param_check(EVP_PKEY_CTX *ctx); +-int q_EVP_PKEY_base_id(EVP_PKEY *a); + int q_RSA_bits(RSA *a); + Q_AUTOTEST_EXPORT int q_OPENSSL_sk_num(OPENSSL_STACK *a); + Q_AUTOTEST_EXPORT void q_OPENSSL_sk_pop_free(OPENSSL_STACK *a, void (*b)(void *)); +@@ -246,7 +245,7 @@ Q_AUTOTEST_EXPORT void q_OPENSSL_sk_push(OPENSSL_STACK *st, void *data); + Q_AUTOTEST_EXPORT void q_OPENSSL_sk_free(OPENSSL_STACK *a); + Q_AUTOTEST_EXPORT void * q_OPENSSL_sk_value(OPENSSL_STACK *a, int b); + int q_SSL_session_reused(SSL *a); +-unsigned long q_SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op); ++qssloptions q_SSL_CTX_set_options(SSL_CTX *ctx, qssloptions op); + int q_OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings); + size_t q_SSL_get_client_random(SSL *a, unsigned char *out, size_t outlen); + size_t q_SSL_SESSION_get_master_key(const SSL_SESSION *session, unsigned char *out, size_t outlen); +@@ -510,7 +509,6 @@ const SSL_CIPHER *q_SSL_get_current_cipher(SSL *a); + int q_SSL_version(const SSL *a); + int q_SSL_get_error(SSL *a, int b); + STACK_OF(X509) *q_SSL_get_peer_cert_chain(SSL *a); +-X509 *q_SSL_get_peer_certificate(SSL *a); + long q_SSL_get_verify_result(const SSL *a); + SSL *q_SSL_new(SSL_CTX *a); + SSL_CTX *q_SSL_get_SSL_CTX(SSL *a); +@@ -582,10 +580,7 @@ DH *q_DH_new(); + void q_DH_free(DH *dh); + DH *q_d2i_DHparams(DH **a, const unsigned char **pp, long length); + int q_i2d_DHparams(DH *a, unsigned char **p); +- +-#ifndef OPENSSL_NO_DEPRECATED_3_0 + int q_DH_check(DH *dh, int *codes); +-#endif // OPENSSL_NO_DEPRECATED_3_0 + + BIGNUM *q_BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); + #define q_SSL_CTX_set_tmp_dh(ctx, dh) q_SSL_CTX_ctrl((ctx), SSL_CTRL_SET_TMP_DH, 0, (char *)dh) +@@ -754,6 +749,17 @@ void q_CRYPTO_free(void *str, const char *file, int line); + int q_SSL_CTX_get_security_level(const SSL_CTX *ctx); + void q_SSL_CTX_set_security_level(SSL_CTX *ctx, int level); + ++// Here we have the ones that make difference between OpenSSL pre/post v3: ++#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 ++X509 *q_SSL_get1_peer_certificate(SSL *a); ++#define q_SSL_get_peer_certificate q_SSL_get1_peer_certificate ++int q_EVP_PKEY_get_base_id(const EVP_PKEY *pkey); ++#define q_EVP_PKEY_base_id q_EVP_PKEY_get_base_id ++#else ++X509 *q_SSL_get_peer_certificate(SSL *a); ++int q_EVP_PKEY_base_id(EVP_PKEY *a); ++#endif // OPENSSL_VERSION_MAJOR >= 3 ++ + QT_END_NAMESPACE + + #endif +diff --git a/qtbase/src/platformsupport/eglconvenience/qt_egl_p.h b/qtbase/src/platformsupport/eglconvenience/qt_egl_p.h +index bf37d07fd8..dbd42fb799 100644 +--- a/qtbase/src/platformsupport/eglconvenience/qt_egl_p.h ++++ b/qtbase/src/platformsupport/eglconvenience/qt_egl_p.h +@@ -61,7 +61,11 @@ + # if !defined(Q_OS_INTEGRITY) + # define WIN_INTERFACE_CUSTOM // NV + # endif // Q_OS_INTEGRITY +-#endif // QT_EGL_NO_X11 ++#else // QT_EGL_NO_X11 ++// If one has an eglplatform.h with https://github.com/KhronosGroup/EGL-Registry/pull/130 ++// that needs USE_X11 to be defined. ++# define USE_X11 ++#endif + + #ifdef QT_EGL_WAYLAND + # define WAYLAND // NV +diff --git a/qtbase/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/qtbase/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +index 159b490ce0..00aa80cd58 100644 +--- a/qtbase/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp ++++ b/qtbase/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +@@ -567,6 +567,8 @@ void QFontconfigDatabase::populateFontDatabase() + fonts = FcFontList(nullptr, pattern, os); + FcObjectSetDestroy(os); + FcPatternDestroy(pattern); ++ if (!fonts) ++ return; + } + + for (int i = 0; i < fonts->nfont; i++) +diff --git a/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon.cpp b/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon.cpp +index b713c19447..7cb9a8c79a 100644 +--- a/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon.cpp ++++ b/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon.cpp +@@ -95,6 +95,7 @@ static constexpr const auto KeyTbl = qMakeArray( + Xkb2Qt, + Xkb2Qt, + Xkb2Qt, ++ Xkb2Qt, + Xkb2Qt<0x1005FF60, Qt::Key_SysReq>, // hardcoded Sun SysReq + Xkb2Qt<0x1007ff00, Qt::Key_SysReq>, // hardcoded X386 SysReq + +@@ -471,7 +472,7 @@ QVector QXkbCommon::toKeysym(QKeyEvent *event) + } else if (event->modifiers() & Qt::KeypadModifier) { + if (qtKey >= Qt::Key_0 && qtKey <= Qt::Key_9) + keysyms.append(XKB_KEY_KP_0 + (qtKey - Qt::Key_0)); +- } else if (isLatin(qtKey) && event->text().isUpper()) { ++ } else if (isLatin1(qtKey) && event->text().isUpper()) { + keysyms.append(qtKey); + } + +@@ -523,7 +524,7 @@ int QXkbCommon::keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers modifie + // With standard shortcuts we should prefer a latin character, this is + // for checks like "some qkeyevent == QKeySequence::Copy" to work even + // when using for example 'russian' keyboard layout. +- if (!QXkbCommon::isLatin(keysym)) { ++ if (!QXkbCommon::isLatin1(keysym)) { + xkb_keysym_t latinKeysym = QXkbCommon::lookupLatinKeysym(state, code); + if (latinKeysym != XKB_KEY_NoSymbol) + keysym = latinKeysym; +@@ -546,7 +547,7 @@ static int keysymToQtKey_internal(xkb_keysym_t keysym, Qt::KeyboardModifiers mod + } else if (keysym >= XKB_KEY_KP_0 && keysym <= XKB_KEY_KP_9) { + // numeric keypad keys + qtKey = Qt::Key_0 + (keysym - XKB_KEY_KP_0); +- } else if (QXkbCommon::isLatin(keysym)) { ++ } else if (QXkbCommon::isLatin1(keysym)) { + qtKey = QXkbCommon::qxkbcommon_xkb_keysym_to_upper(keysym); + } else { + // check if we have a direct mapping +@@ -678,7 +679,7 @@ QList QXkbCommon::possibleKeys(xkb_state *state, const QKeyEvent *event, + Qt::KeyboardModifiers neededMods = ModsTbl[i]; + if ((modifiers & neededMods) == neededMods) { + if (i == 8) { +- if (isLatin(baseQtKey)) ++ if (isLatin1(baseQtKey)) + continue; + // add a latin key as a fall back key + sym = lookupLatinKeysym(state, keycode); +@@ -733,7 +734,7 @@ void QXkbCommon::verifyHasLatinLayout(xkb_keymap *keymap) + for (xkb_layout_index_t layout = 0; layout < layoutCount; ++layout) { + for (xkb_keycode_t code = minKeycode; code < maxKeycode; ++code) { + xkb_keymap_key_get_syms_by_level(keymap, code, layout, 0, &keysyms); +- if (keysyms && isLatin(keysyms[0])) ++ if (keysyms && isLatin1(keysyms[0])) + nrLatinKeys++; + if (nrLatinKeys > 10) // arbitrarily chosen threshold + return; +@@ -766,7 +767,7 @@ xkb_keysym_t QXkbCommon::lookupLatinKeysym(xkb_state *state, xkb_keycode_t keyco + xkb_level_index_t level = xkb_state_key_get_level(state, keycode, layout); + if (xkb_keymap_key_get_syms_by_level(keymap, keycode, layout, level, &syms) != 1) + continue; +- if (isLatin(syms[0])) { ++ if (isLatin1(syms[0])) { + sym = syms[0]; + break; + } +diff --git a/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h b/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h +index 561eae03db..8389bd8f5a 100644 +--- a/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h ++++ b/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h +@@ -94,8 +94,8 @@ public: + static void verifyHasLatinLayout(xkb_keymap *keymap); + static xkb_keysym_t lookupLatinKeysym(xkb_state *state, xkb_keycode_t keycode); + +- static bool isLatin(xkb_keysym_t sym) { +- return ((sym >= 'a' && sym <= 'z') || (sym >= 'A' && sym <= 'Z')); ++ static bool isLatin1(xkb_keysym_t sym) { ++ return sym <= 0xff; + } + static bool isKeypad(xkb_keysym_t sym) { + return sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9; +diff --git a/qtbase/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/qtbase/src/platformsupport/kmsconvenience/qkmsdevice.cpp +index 8cd7f9b368..406f84663f 100644 +--- a/qtbase/src/platformsupport/kmsconvenience/qkmsdevice.cpp ++++ b/qtbase/src/platformsupport/kmsconvenience/qkmsdevice.cpp +@@ -318,7 +318,7 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, + + if (current < 0 && crtc_mode.clock != 0) { + modes << crtc_mode; +- current = mode.size() - 1; ++ current = modes.size() - 1; + } + + if (configuration == OutputConfigCurrent) +diff --git a/qtbase/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/qtbase/src/platformsupport/linuxaccessibility/atspiadaptor.cpp +index 9153fd20bb..255ea5e33e 100644 +--- a/qtbase/src/platformsupport/linuxaccessibility/atspiadaptor.cpp ++++ b/qtbase/src/platformsupport/linuxaccessibility/atspiadaptor.cpp +@@ -194,6 +194,9 @@ QString AtSpiAdaptor::introspect(const QString &path) const + " \n" + " \n" + " \n" ++ " \n" ++ " \n" ++ " \n" + " \n" + ); + +@@ -913,8 +916,17 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event) + } + case QAccessible::NameChanged: { + if (sendObject || sendObject_property_change || sendObject_property_change_accessible_name) { +- QString path = pathForInterface(event->accessibleInterface()); +- QVariantList args = packDBusSignalArguments(QLatin1String("accessible-name"), 0, 0, variantForPath(path)); ++ QAccessibleInterface *iface = event->accessibleInterface(); ++ if (!iface) { ++ qCDebug(lcAccessibilityAtspi, ++ "NameChanged event from invalid accessible."); ++ return; ++ } ++ ++ QString path = pathForInterface(iface); ++ QVariantList args = packDBusSignalArguments( ++ QLatin1String("accessible-name"), 0, 0, ++ QVariant::fromValue(QDBusVariant(iface->text(QAccessible::Name)))); + sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT), + QLatin1String("PropertyChange"), args); + } +@@ -922,8 +934,17 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event) + } + case QAccessible::DescriptionChanged: { + if (sendObject || sendObject_property_change || sendObject_property_change_accessible_description) { +- QString path = pathForInterface(event->accessibleInterface()); +- QVariantList args = packDBusSignalArguments(QLatin1String("accessible-description"), 0, 0, variantForPath(path)); ++ QAccessibleInterface *iface = event->accessibleInterface(); ++ if (!iface) { ++ qCDebug(lcAccessibilityAtspi, ++ "DescriptionChanged event from invalid accessible."); ++ return; ++ } ++ ++ QString path = pathForInterface(iface); ++ QVariantList args = packDBusSignalArguments( ++ QLatin1String("accessible-description"), 0, 0, ++ QVariant::fromValue(QDBusVariant(iface->text(QAccessible::Description)))); + sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT), + QLatin1String("PropertyChange"), args); + } +@@ -1038,7 +1059,9 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event) + // Combo Box with AT-SPI likes to be special + // It requires a name-change to update caches and then selection-changed + QString path = pathForInterface(iface); +- QVariantList args1 = packDBusSignalArguments(QLatin1String("accessible-name"), 0, 0, variantForPath(path)); ++ QVariantList args1 = packDBusSignalArguments( ++ QLatin1String("accessible-name"), 0, 0, ++ QVariant::fromValue(QDBusVariant(iface->text(QAccessible::Name)))); + sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT), + QLatin1String("PropertyChange"), args1); + QVariantList args2 = packDBusSignalArguments(QString(), 0, 0, QVariant::fromValue(QDBusVariant(QVariant(0)))); +@@ -1358,6 +1381,26 @@ void AtSpiAdaptor::registerApplication() + delete registry; + } + ++namespace { ++QString accessibleIdForAccessible(QAccessibleInterface *accessible) ++{ ++ QString result; ++ while (accessible) { ++ if (!result.isEmpty()) ++ result.prepend(QLatin1Char('.')); ++ if (auto obj = accessible->object()) { ++ const QString name = obj->objectName(); ++ if (!name.isEmpty()) ++ result.prepend(name); ++ else ++ result.prepend(QString::fromUtf8(obj->metaObject()->className())); ++ } ++ accessible = accessible->parent(); ++ } ++ return result; ++} ++} // namespace ++ + // Accessible + bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection) + { +@@ -1441,6 +1484,9 @@ bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QS + children << ref; + } + connection.send(message.createReply(QVariant::fromValue(children))); ++ } else if (function == QLatin1String("GetAccessibleId")) { ++ sendReply(connection, message, ++ QVariant::fromValue(QDBusVariant(accessibleIdForAccessible(interface)))); + } else { + qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::accessibleInterface does not implement " << function << message.path(); + return false; +diff --git a/qtbase/src/platformsupport/linuxaccessibility/dbusconnection.cpp b/qtbase/src/platformsupport/linuxaccessibility/dbusconnection.cpp +index 45ddc8e496..cc734abc63 100644 +--- a/qtbase/src/platformsupport/linuxaccessibility/dbusconnection.cpp ++++ b/qtbase/src/platformsupport/linuxaccessibility/dbusconnection.cpp +@@ -69,6 +69,21 @@ QT_BEGIN_NAMESPACE + DBusConnection::DBusConnection(QObject *parent) + : QObject(parent), m_a11yConnection(QString()), m_enabled(false) + { ++ // If the bus is explicitly set via env var it overrides everything else. ++ QByteArray addressEnv = qgetenv("AT_SPI_BUS_ADDRESS"); ++ if (!addressEnv.isEmpty()) { ++ // Only connect on next loop run, connections to our enabled signal are ++ // only established after the ctor returns. ++ QMetaObject::invokeMethod( ++ this, ++ [this, addressEnv] { ++ m_enabled = true; ++ connectA11yBus(QString::fromLocal8Bit(addressEnv)); ++ }, ++ Qt::QueuedConnection); ++ return; ++ } ++ + // Start monitoring if "org.a11y.Bus" is registered as DBus service. + QDBusConnection c = QDBusConnection::sessionBus(); + if (!c.isConnected()) { +diff --git a/qtbase/src/platformsupport/services/genericunix/qgenericunixservices.cpp b/qtbase/src/platformsupport/services/genericunix/qgenericunixservices.cpp +index 1a3cab275d..2abe039126 100644 +--- a/qtbase/src/platformsupport/services/genericunix/qgenericunixservices.cpp ++++ b/qtbase/src/platformsupport/services/genericunix/qgenericunixservices.cpp +@@ -51,6 +51,9 @@ + #include + #include + ++#include ++#include ++ + #if QT_CONFIG(dbus) + // These QtCore includes are needed for xdg-desktop-portal support + #include +@@ -58,6 +61,8 @@ + #include + #include + ++#include ++ + #include + #include + #include +@@ -142,6 +147,8 @@ static inline bool detectWebBrowser(const QByteArray &desktop, + } + + if (desktop == QByteArray("KDE")) { ++ if (checkExecutable(QStringLiteral("kde-open5"), browser)) ++ return true; + // Konqueror launcher + if (checkExecutable(QStringLiteral("kfmclient"), browser)) { + browser->append(QLatin1String(" exec")); +@@ -296,8 +303,135 @@ static inline QDBusMessage xdgDesktopPortalSendEmail(const QUrl &url) + + return QDBusConnection::sessionBus().call(message); + } ++ ++namespace { ++struct XDGDesktopColor ++{ ++ double r = 0; ++ double g = 0; ++ double b = 0; ++ ++ QColor toQColor() const ++ { ++ constexpr auto rgbMax = 255; ++ return { static_cast(r * rgbMax), static_cast(g * rgbMax), ++ static_cast(b * rgbMax) }; ++ } ++}; ++ ++const QDBusArgument &operator>>(const QDBusArgument &argument, XDGDesktopColor &myStruct) ++{ ++ argument.beginStructure(); ++ argument >> myStruct.r >> myStruct.g >> myStruct.b; ++ argument.endStructure(); ++ return argument; ++} ++ ++class XdgDesktopPortalColorPicker : public QPlatformServiceColorPicker ++{ ++ Q_OBJECT ++public: ++ XdgDesktopPortalColorPicker(const QString &parentWindowId, QWindow *parent) ++ : QPlatformServiceColorPicker(parent), m_parentWindowId(parentWindowId) ++ { ++ } ++ ++ void pickColor() override ++ { ++ // DBus signature: ++ // PickColor (IN s parent_window, ++ // IN a{sv} options ++ // OUT o handle) ++ // Options: ++ // handle_token (s) - A string that will be used as the last element of the @handle. ++ ++ QDBusMessage message = QDBusMessage::createMethodCall( ++ QStringLiteral("org.freedesktop.portal.Desktop"), QStringLiteral("/org/freedesktop/portal/desktop"), ++ QStringLiteral("org.freedesktop.portal.Screenshot"), QStringLiteral("PickColor")); ++ message << m_parentWindowId << QVariantMap(); ++ ++ QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message); ++ auto watcher = new QDBusPendingCallWatcher(pendingCall, this); ++ connect(watcher, &QDBusPendingCallWatcher::finished, this, ++ [this](QDBusPendingCallWatcher *watcher) { ++ watcher->deleteLater(); ++ QDBusPendingReply reply = *watcher; ++ if (reply.isError()) { ++ qWarning("DBus call to pick color failed: %s", ++ qPrintable(reply.error().message())); ++ Q_EMIT colorPicked({}); ++ } else { ++ QDBusConnection::sessionBus().connect( ++ QStringLiteral("org.freedesktop.portal.Desktop"), reply.value().path(), ++ QStringLiteral("org.freedesktop.portal.Request"), QStringLiteral("Response"), this, ++ // clang-format off ++ SLOT(gotColorResponse(uint,QVariantMap)) ++ // clang-format on ++ ); ++ } ++ }); ++ } ++ ++private Q_SLOTS: ++ void gotColorResponse(uint result, const QVariantMap &map) ++ { ++ if (result != 0) ++ return; ++ XDGDesktopColor color{}; ++ map.value(QStringLiteral("color")).value() >> color; ++ Q_EMIT colorPicked(color.toQColor()); ++ deleteLater(); ++ } ++ ++private: ++ const QString m_parentWindowId; ++}; ++} // namespace ++ + #endif // QT_CONFIG(dbus) + ++QGenericUnixServices::QGenericUnixServices() ++{ ++#if QT_CONFIG(dbus) ++ if (qEnvironmentVariableIntValue("QT_NO_XDG_DESKTOP_PORTAL") > 0) { ++ return; ++ } ++ QDBusMessage message = QDBusMessage::createMethodCall( ++ QStringLiteral("org.freedesktop.portal.Desktop"), QStringLiteral("/org/freedesktop/portal/desktop"), ++ QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("Get")); ++ message << QStringLiteral("org.freedesktop.portal.Screenshot") ++ << QStringLiteral("version"); ++ ++ QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message); ++ auto watcher = new QDBusPendingCallWatcher(pendingCall); ++ QObject::connect(watcher, &QDBusPendingCallWatcher::finished, watcher, ++ [this](QDBusPendingCallWatcher *watcher) { ++ watcher->deleteLater(); ++ QDBusPendingReply reply = *watcher; ++ if (!reply.isError() && reply.value().toUInt() >= 2) ++ m_hasScreenshotPortalWithColorPicking = true; ++ }); ++ ++#endif ++} ++ ++QPlatformServiceColorPicker *QGenericUnixServices::colorPicker(QWindow *parent) ++{ ++#if QT_CONFIG(dbus) ++ // Make double sure that we are in a wayland environment. In particular check ++ // WAYLAND_DISPLAY so also XWayland apps benefit from portal-based color picking. ++ // Outside wayland we'll rather rely on other means than the XDG desktop portal. ++ if (!qEnvironmentVariableIsEmpty("WAYLAND_DISPLAY") ++ || QGuiApplication::platformName().startsWith(QLatin1String("wayland"))) { ++ return new XdgDesktopPortalColorPicker(portalWindowIdentifier(parent), parent); ++ } ++ return nullptr; ++#else ++ Q_UNUSED(parent); ++ return nullptr; ++#endif ++} ++ + QByteArray QGenericUnixServices::desktopEnvironment() const + { + static const QByteArray result = detectDesktopEnvironment(); +@@ -352,6 +486,8 @@ bool QGenericUnixServices::openDocument(const QUrl &url) + } + + #else ++QGenericUnixServices::QGenericUnixServices() = default; ++ + QByteArray QGenericUnixServices::desktopEnvironment() const + { + return QByteArrayLiteral("UNKNOWN"); +@@ -371,6 +507,30 @@ bool QGenericUnixServices::openDocument(const QUrl &url) + return false; + } + ++QPlatformServiceColorPicker *QGenericUnixServices::colorPicker(QWindow *parent) ++{ ++ Q_UNUSED(parent); ++ return nullptr; ++} ++ + #endif // QT_NO_MULTIPROCESS + ++QString QGenericUnixServices::portalWindowIdentifier(QWindow *window) ++{ ++ if (QGuiApplication::platformName() == QLatin1String("xcb")) ++ return QStringLiteral("x11:") + QString::number(window->winId(), 16); ++ return QString(); ++} ++ ++bool QGenericUnixServices::hasCapability(Capability capability) const ++{ ++ switch (capability) { ++ case Capability::ColorPicking: ++ return m_hasScreenshotPortalWithColorPicking; ++ } ++ return false; ++} ++ + QT_END_NAMESPACE ++ ++#include "qgenericunixservices.moc" +diff --git a/qtbase/src/platformsupport/services/genericunix/qgenericunixservices_p.h b/qtbase/src/platformsupport/services/genericunix/qgenericunixservices_p.h +index 8ac3de6f03..30924e64bd 100644 +--- a/qtbase/src/platformsupport/services/genericunix/qgenericunixservices_p.h ++++ b/qtbase/src/platformsupport/services/genericunix/qgenericunixservices_p.h +@@ -59,16 +59,21 @@ QT_BEGIN_NAMESPACE + class QGenericUnixServices : public QPlatformServices + { + public: +- QGenericUnixServices() {} ++ QGenericUnixServices(); + + QByteArray desktopEnvironment() const override; + ++ bool hasCapability(Capability capability) const override; + bool openUrl(const QUrl &url) override; + bool openDocument(const QUrl &url) override; ++ QPlatformServiceColorPicker *colorPicker(QWindow *parent = nullptr) override; ++ ++ virtual QString portalWindowIdentifier(QWindow *window); + + private: + QString m_webBrowser; + QString m_documentLauncher; ++ bool m_hasScreenshotPortalWithColorPicking = false; + }; + + QT_END_NAMESPACE +diff --git a/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp b/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp +index 09470bccc6..cc7c7d4d8a 100644 +--- a/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp ++++ b/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp +@@ -69,6 +69,7 @@ const QString MenuBarPath = QLatin1String("/MenuBar"); + */ + QDBusMenuConnection::QDBusMenuConnection(QObject *parent, const QString &serviceName) + : QObject(parent) ++ , m_serviceName(serviceName) + , m_connection(serviceName.isNull() ? QDBusConnection::sessionBus() + : QDBusConnection::connectToBus(QDBusConnection::SessionBus, serviceName)) + , m_dbusWatcher(new QDBusServiceWatcher(StatusNotifierWatcherService, m_connection, QDBusServiceWatcher::WatchForRegistration, this)) +@@ -83,6 +84,12 @@ QDBusMenuConnection::QDBusMenuConnection(QObject *parent, const QString &service + #endif + } + ++QDBusMenuConnection::~QDBusMenuConnection() ++{ ++ if (!m_serviceName.isEmpty() && m_connection.isConnected()) ++ QDBusConnection::disconnectFromBus(m_serviceName); ++} ++ + void QDBusMenuConnection::dbusError(const QDBusError &error) + { + qWarning() << "QDBusTrayIcon encountered a D-Bus error:" << error; +@@ -105,13 +112,7 @@ void QDBusMenuConnection::unregisterTrayIconMenu(QDBusTrayIcon *item) + + bool QDBusMenuConnection::registerTrayIcon(QDBusTrayIcon *item) + { +- bool success = connection().registerService(item->instanceId()); +- if (!success) { +- qWarning() << "failed to register service" << item->instanceId(); +- return false; +- } +- +- success = connection().registerObject(StatusNotifierItemPath, item); ++ bool success = connection().registerObject(StatusNotifierItemPath, item); + if (!success) { + unregisterTrayIcon(item); + qWarning() << "failed to register" << item->instanceId() << StatusNotifierItemPath; +@@ -126,21 +127,18 @@ bool QDBusMenuConnection::registerTrayIcon(QDBusTrayIcon *item) + + bool QDBusMenuConnection::registerTrayIconWithWatcher(QDBusTrayIcon *item) + { ++ Q_UNUSED(item); + QDBusMessage registerMethod = QDBusMessage::createMethodCall( + StatusNotifierWatcherService, StatusNotifierWatcherPath, StatusNotifierWatcherService, + QLatin1String("RegisterStatusNotifierItem")); +- registerMethod.setArguments(QVariantList() << item->instanceId()); ++ registerMethod.setArguments(QVariantList() << m_connection.baseService()); + return m_connection.callWithCallback(registerMethod, this, SIGNAL(trayIconRegistered()), SLOT(dbusError(QDBusError))); + } + +-bool QDBusMenuConnection::unregisterTrayIcon(QDBusTrayIcon *item) ++void QDBusMenuConnection::unregisterTrayIcon(QDBusTrayIcon *item) + { + unregisterTrayIconMenu(item); + connection().unregisterObject(StatusNotifierItemPath); +- bool success = connection().unregisterService(item->instanceId()); +- if (!success) +- qWarning() << "failed to unregister service" << item->instanceId(); +- return success; + } + #endif // QT_NO_SYSTEMTRAYICON + +diff --git a/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h b/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h +index f484795fbb..97bdfabb85 100644 +--- a/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h ++++ b/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h +@@ -70,6 +70,7 @@ class QDBusMenuConnection : public QObject + + public: + QDBusMenuConnection(QObject *parent = nullptr, const QString &serviceName = QString()); ++ ~QDBusMenuConnection(); + QDBusConnection connection() const { return m_connection; } + QDBusServiceWatcher *dbusWatcher() const { return m_dbusWatcher; } + bool isStatusNotifierHostRegistered() const { return m_statusNotifierHostRegistered; } +@@ -78,7 +79,7 @@ public: + void unregisterTrayIconMenu(QDBusTrayIcon *item); + bool registerTrayIcon(QDBusTrayIcon *item); + bool registerTrayIconWithWatcher(QDBusTrayIcon *item); +- bool unregisterTrayIcon(QDBusTrayIcon *item); ++ void unregisterTrayIcon(QDBusTrayIcon *item); + #endif // QT_NO_SYSTEMTRAYICON + + Q_SIGNALS: +@@ -90,6 +91,7 @@ private Q_SLOTS: + void dbusError(const QDBusError &error); + + private: ++ QString m_serviceName; + QDBusConnection m_connection; + QDBusServiceWatcher *m_dbusWatcher; + bool m_statusNotifierHostRegistered; +diff --git a/qtbase/src/platformsupport/themes/genericunix/dbustray/qdbustrayicon.cpp b/qtbase/src/platformsupport/themes/genericunix/dbustray/qdbustrayicon.cpp +index bede70975a..76bfec5e5a 100644 +--- a/qtbase/src/platformsupport/themes/genericunix/dbustray/qdbustrayicon.cpp ++++ b/qtbase/src/platformsupport/themes/genericunix/dbustray/qdbustrayicon.cpp +@@ -71,8 +71,12 @@ Q_LOGGING_CATEGORY(qLcTray, "qt.qpa.tray") + static QString iconTempPath() + { + QString tempPath = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation); +- if (!tempPath.isEmpty()) ++ if (!tempPath.isEmpty()) { ++ QString flatpakId = qEnvironmentVariable("FLATPAK_ID"); ++ if (!flatpakId.isEmpty() && QFileInfo::exists(QLatin1String("/.flatpak-info"))) ++ tempPath += QLatin1String("/app/") + flatpakId; + return tempPath; ++ } + + tempPath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation); + +diff --git a/qtbase/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/qtbase/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp +index cb1b39db64..6e01af052c 100644 +--- a/qtbase/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp ++++ b/qtbase/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp +@@ -755,6 +755,9 @@ QVariant QGnomeTheme::themeHint(QPlatformTheme::ThemeHint hint) const + return QVariant(QChar(0x2022)); + case QPlatformTheme::UiEffects: + return QVariant(int(HoverEffect)); ++ case QPlatformTheme::ButtonPressKeys: ++ return QVariant::fromValue( ++ QList({ Qt::Key_Space, Qt::Key_Return, Qt::Key_Enter, Qt::Key_Select })); + default: + break; + } +diff --git a/qtbase/src/plugins/platforms/eglfs/api/qeglfscursor.cpp b/qtbase/src/plugins/platforms/eglfs/api/qeglfscursor.cpp +index 98e05195ee..1e92f43dec 100644 +--- a/qtbase/src/plugins/platforms/eglfs/api/qeglfscursor.cpp ++++ b/qtbase/src/plugins/platforms/eglfs/api/qeglfscursor.cpp +@@ -343,8 +343,7 @@ void QEglFSCursor::paintOnScreen() + // screens are siblings of each other. When not enabled, the sibling list + // only contains m_screen itself. + for (QPlatformScreen *screen : m_screen->virtualSiblings()) { +- if (screen->geometry().contains(cr.topLeft().toPoint() + m_cursor.hotSpot) +- && QOpenGLContext::currentContext()->screen() == screen->screen()) ++ if (screen->geometry().contains(cr.topLeft().toPoint() + m_cursor.hotSpot)) + { + cr.translate(-screen->geometry().topLeft()); + const QSize screenSize = screen->geometry().size(); +@@ -468,11 +467,12 @@ void QEglFSCursor::draw(const QRectF &r) + { + StateSaver stateSaver; + +- QEglFSCursorData &gfx = static_cast(QOpenGLContext::currentContext()->handle())->cursorData; +- if (!gfx.program) { +- // one time initialization ++ // one time initialization ++ if (!QOpenGLFunctions::d_ptr) + initializeOpenGLFunctions(); + ++ QEglFSCursorData &gfx = static_cast(QOpenGLContext::currentContext()->handle())->cursorData; ++ if (!gfx.program) { + createShaderPrograms(); + + if (!gfx.atlasTexture) { +diff --git a/qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp b/qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp +index 645a0ae2e9..3e0e406f1a 100644 +--- a/qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp ++++ b/qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp +@@ -179,7 +179,7 @@ void QEglFSKmsEventReader::create(QEglFSKmsDevice *device) + + m_device = device; + +- qCDebug(qLcEglfsKmsDebug, "Initalizing event reader for device %p fd %d", ++ qCDebug(qLcEglfsKmsDebug, "Initializing event reader for device %p fd %d", + m_device, m_device->fd()); + + m_thread = new QEglFSKmsEventReaderThread(m_device->fd()); +diff --git a/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.cpp b/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.cpp +index 141fb68a23..d4294d425a 100644 +--- a/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.cpp ++++ b/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.cpp +@@ -122,11 +122,13 @@ QOffscreenIntegration::QOffscreenIntegration() + #endif + m_services.reset(new QPlatformServices); + +- QWindowSystemInterface::handleScreenAdded(new QOffscreenScreen); ++ m_screen = new QOffscreenScreen; ++ QWindowSystemInterface::handleScreenAdded(m_screen); + } + + QOffscreenIntegration::~QOffscreenIntegration() + { ++ QWindowSystemInterface::handleScreenRemoved(m_screen); + } + + void QOffscreenIntegration::initialize() +diff --git a/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.h b/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.h +index 0ea90f6c2f..fe00fde07c 100644 +--- a/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.h ++++ b/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.h +@@ -84,6 +84,7 @@ protected: + #endif + QScopedPointer m_inputContext; + QScopedPointer m_services; ++ QPlatformScreen *m_screen; + mutable QScopedPointer m_nativeInterface; + }; + +diff --git a/qtbase/src/plugins/platforms/windows/qwindowsglcontext.cpp b/qtbase/src/plugins/platforms/windows/qwindowsglcontext.cpp +index 6fa5a8a2b3..1f49f0aefd 100644 +--- a/qtbase/src/plugins/platforms/windows/qwindowsglcontext.cpp ++++ b/qtbase/src/plugins/platforms/windows/qwindowsglcontext.cpp +@@ -48,6 +48,7 @@ + #include + #include + ++#include + #include + + #include +@@ -162,19 +163,25 @@ QFunctionPointer QWindowsOpengl32DLL::resolve(const char *name) + + bool QWindowsOpengl32DLL::init(bool softwareRendering) + { +- const QByteArray opengl32 = QByteArrayLiteral("opengl32.dll"); +- const QByteArray swopengl = QByteArrayLiteral("opengl32sw.dll"); ++ const QByteArray opengl32 = QByteArrayLiteral("opengl32"); ++ const QByteArray swopengl = QByteArrayLiteral("opengl32sw"); ++ bool useSystemLib = false; + + QByteArray openglDll = qgetenv("QT_OPENGL_DLL"); +- if (openglDll.isEmpty()) ++ if (openglDll.isEmpty()) { + openglDll = softwareRendering ? swopengl : opengl32; ++ useSystemLib = !softwareRendering; ++ } + + openglDll = openglDll.toLower(); + m_nonOpengl32 = openglDll != opengl32; + + qCDebug(lcQpaGl) << "Qt: Using WGL and OpenGL from" << openglDll; + +- m_lib = ::LoadLibraryA(openglDll.constData()); ++ if (useSystemLib) ++ m_lib = QSystemLibrary::load((wchar_t*)(QString::fromLatin1(openglDll).utf16())); ++ else ++ m_lib = LoadLibraryA(openglDll.constData()); + if (!m_lib) { + qErrnoWarning(::GetLastError(), "Failed to load %s", openglDll.constData()); + return false; +@@ -184,7 +191,7 @@ bool QWindowsOpengl32DLL::init(bool softwareRendering) + // Load opengl32.dll always. GDI functions like ChoosePixelFormat do + // GetModuleHandle for opengl32.dll and behave differently (and call back into + // opengl32) when the module is present. This is fine for dummy contexts and windows. +- ::LoadLibraryA("opengl32.dll"); ++ QSystemLibrary::load(L"opengl32"); + } + + wglCreateContext = reinterpret_cast(resolve("wglCreateContext")); +diff --git a/qtbase/src/plugins/platforms/windows/qwindowsopengltester.cpp b/qtbase/src/plugins/platforms/windows/qwindowsopengltester.cpp +index d7d186e804..9eb4011bf2 100644 +--- a/qtbase/src/plugins/platforms/windows/qwindowsopengltester.cpp ++++ b/qtbase/src/plugins/platforms/windows/qwindowsopengltester.cpp +@@ -49,6 +49,7 @@ + #include + #include + #include ++#include + + #ifndef QT_NO_OPENGL + #include +@@ -396,7 +397,7 @@ bool QWindowsOpenGLTester::testDesktopGL() + + // Test #1: Load opengl32.dll and try to resolve an OpenGL 2 function. + // This will typically fail on systems that do not have a real OpenGL driver. +- lib = LoadLibraryA("opengl32.dll"); ++ lib = QSystemLibrary::load(L"opengl32"); + if (lib) { + CreateContext = reinterpret_cast( + reinterpret_cast(::GetProcAddress(lib, "wglCreateContext"))); +diff --git a/qtbase/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp b/qtbase/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp +index 1afa00cfc9..118af6ce73 100644 +--- a/qtbase/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp ++++ b/qtbase/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp +@@ -41,6 +41,7 @@ + + #include + #include ++#include + #include + + #include +diff --git a/qtbase/src/plugins/platforms/xcb/qxcbconnection.cpp b/qtbase/src/plugins/platforms/xcb/qxcbconnection.cpp +index 9e2a37a6a1..e6e175a118 100644 +--- a/qtbase/src/plugins/platforms/xcb/qxcbconnection.cpp ++++ b/qtbase/src/plugins/platforms/xcb/qxcbconnection.cpp +@@ -488,12 +488,12 @@ void QXcbConnection::printXcbError(const char *message, xcb_generic_error_t *err + uint clamped_error_code = qMin(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1); + uint clamped_major_code = qMin(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1); + +- qCWarning(lcQpaXcb, "%s: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d", +- message, +- int(error->error_code), xcb_errors[clamped_error_code], +- int(error->sequence), int(error->resource_id), +- int(error->major_code), xcb_protocol_request_codes[clamped_major_code], +- int(error->minor_code)); ++ qCDebug(lcQpaXcb, "%s: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d", ++ message, ++ int(error->error_code), xcb_errors[clamped_error_code], ++ int(error->sequence), int(error->resource_id), ++ int(error->major_code), xcb_protocol_request_codes[clamped_major_code], ++ int(error->minor_code)); + } + + static Qt::MouseButtons translateMouseButtons(int s) +@@ -702,6 +702,8 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) + QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(propertyNotify->window); + if (virtualDesktop) + virtualDesktop->updateWorkArea(); ++ } else if (propertyNotify->atom == atom(QXcbAtom::_NET_SUPPORTED)) { ++ m_wmSupport->updateNetWMAtoms(); + } else { + HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent); + } +@@ -750,7 +752,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) + case XCB_XKB_NEW_KEYBOARD_NOTIFY: { + xcb_xkb_new_keyboard_notify_event_t *ev = &xkb_event->new_keyboard_notify; + if (ev->changed & XCB_XKB_NKN_DETAIL_KEYCODES) +- m_keyboard->updateKeymap(ev); ++ m_keyboard->updateKeymap(); + break; + } + default: +diff --git a/qtbase/src/plugins/platforms/xcb/qxcbintegration.cpp b/qtbase/src/plugins/platforms/xcb/qxcbintegration.cpp +index 76869ced60..02d2eebb56 100644 +--- a/qtbase/src/plugins/platforms/xcb/qxcbintegration.cpp ++++ b/qtbase/src/plugins/platforms/xcb/qxcbintegration.cpp +@@ -274,8 +274,7 @@ QPlatformWindow *QXcbIntegration::createForeignWindow(QWindow *window, WId nativ + #ifndef QT_NO_OPENGL + QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const + { +- QXcbScreen *screen = static_cast(context->screen()->handle()); +- QXcbGlIntegration *glIntegration = screen->connection()->glIntegration(); ++ QXcbGlIntegration *glIntegration = defaultConnection()->glIntegration(); + if (!glIntegration) { + qWarning("QXcbIntegration: Cannot create platform OpenGL context, neither GLX nor EGL are enabled"); + return nullptr; +diff --git a/qtbase/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/qtbase/src/plugins/platforms/xcb/qxcbkeyboard.cpp +index efecd7e2d1..e8286381a2 100644 +--- a/qtbase/src/plugins/platforms/xcb/qxcbkeyboard.cpp ++++ b/qtbase/src/plugins/platforms/xcb/qxcbkeyboard.cpp +@@ -365,17 +365,6 @@ void QXcbKeyboard::updateKeymap(xcb_mapping_notify_event_t *event) + updateKeymap(); + } + +-void QXcbKeyboard::updateKeymap(xcb_xkb_new_keyboard_notify_event_t *event) +-{ +- if (!event) +- return; +- +- if (event->deviceID != event->oldDeviceID) +- m_config = false; +- +- updateKeymap(); +-} +- + void QXcbKeyboard::updateKeymap() + { + KeysymModifierMap keysymMods; +@@ -383,6 +372,8 @@ void QXcbKeyboard::updateKeymap() + keysymMods = keysymsToModifiers(); + updateModifiers(keysymMods); + ++ m_config = true; ++ + if (!m_xkbContext) { + m_xkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES)); + if (!m_xkbContext) { +@@ -398,13 +389,8 @@ void QXcbKeyboard::updateKeymap() + if (connection()->hasXKB()) { + m_xkbKeymap.reset(xkb_x11_keymap_new_from_device(m_xkbContext.get(), xcb_connection(), + core_device_id, XKB_KEYMAP_COMPILE_NO_FLAGS)); +- if (m_xkbKeymap) { +- if (m_config) +- m_xkbState.reset(xkb_state_new(m_xkbKeymap.get())); +- else +- m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), xcb_connection(), core_device_id)); +- +- } ++ if (m_xkbKeymap) ++ m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), xcb_connection(), core_device_id)); + } else { + m_xkbKeymap.reset(keymapFromCore(keysymMods)); + if (m_xkbKeymap) +@@ -425,8 +411,6 @@ void QXcbKeyboard::updateKeymap() + updateXKBMods(); + + QXkbCommon::verifyHasLatinLayout(m_xkbKeymap.get()); +- +- m_config = true; + } + + QList QXcbKeyboard::possibleKeys(const QKeyEvent *event) const +diff --git a/qtbase/src/plugins/platforms/xcb/qxcbkeyboard.h b/qtbase/src/plugins/platforms/xcb/qxcbkeyboard.h +index b652c85fe3..0ee08aeff2 100644 +--- a/qtbase/src/plugins/platforms/xcb/qxcbkeyboard.h ++++ b/qtbase/src/plugins/platforms/xcb/qxcbkeyboard.h +@@ -69,7 +69,6 @@ public: + + Qt::KeyboardModifiers translateModifiers(int s) const; + void updateKeymap(xcb_mapping_notify_event_t *event); +- void updateKeymap(xcb_xkb_new_keyboard_notify_event_t *event); + void updateKeymap(); + QList possibleKeys(const QKeyEvent *event) const; + +diff --git a/qtbase/src/plugins/platforms/xcb/qxcbwindow.cpp b/qtbase/src/plugins/platforms/xcb/qxcbwindow.cpp +index ffda7b6a57..863e961f4c 100644 +--- a/qtbase/src/plugins/platforms/xcb/qxcbwindow.cpp ++++ b/qtbase/src/plugins/platforms/xcb/qxcbwindow.cpp +@@ -564,11 +564,6 @@ void QXcbWindow::setGeometry(const QRect &rect) + { + QPlatformWindow::setGeometry(rect); + +- if (shouldDeferTask(Task::SetGeometry)) { +- m_deferredGeometry = rect; +- return; +- } +- + propagateSizeHints(); + + QXcbScreen *currentScreen = xcbScreen(); +@@ -693,9 +688,6 @@ void QXcbWindow::setVisible(bool visible) + + void QXcbWindow::show() + { +- if (shouldDeferTask(Task::Map)) +- return; +- + if (window()->isTopLevel()) { + + // update WM_NORMAL_HINTS +@@ -706,7 +698,7 @@ void QXcbWindow::show() + if (isTransient(window())) { + const QWindow *tp = window()->transientParent(); + if (tp && tp->handle()) +- transientXcbParent = static_cast(tp->handle())->winId(); ++ transientXcbParent = tp->handle()->winId(); + // Default to client leader if there is no transient parent, else modal dialogs can + // be hidden by their parents. + if (!transientXcbParent) +@@ -746,10 +738,6 @@ void QXcbWindow::show() + + void QXcbWindow::hide() + { +- if (shouldDeferTask(Task::Unmap)) +- return; +- +- m_wmStateValid = false; + xcb_unmap_window(xcb_connection(), m_window); + + // send synthetic UnmapNotify event according to icccm 4.1.4 +@@ -909,9 +897,6 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates() + + void QXcbWindow::setWindowFlags(Qt::WindowFlags flags) + { +- if (shouldDeferTask(Task::SetWindowFlags)) +- return; +- + Qt::WindowType type = static_cast(int(flags & Qt::WindowType_Mask)); + + if (type == Qt::ToolTip) +@@ -941,8 +926,6 @@ void QXcbWindow::setWindowFlags(Qt::WindowFlags flags) + + setTransparentForMouseEvents(flags & Qt::WindowTransparentForInput); + updateDoesNotAcceptFocus(flags & Qt::WindowDoesNotAcceptFocus); +- +- m_isWmManagedWindow = !(flags & Qt::X11BypassWindowManagerHint); + } + + void QXcbWindow::setMotifWmHints(Qt::WindowFlags flags) +@@ -1142,9 +1125,6 @@ void QXcbWindow::setWindowState(Qt::WindowStates state) + if (state == m_windowState) + return; + +- if (shouldDeferTask(Task::SetWindowState)) +- return; +- + // unset old state + if (m_windowState & Qt::WindowMinimized) + xcb_map_window(xcb_connection(), m_window); +@@ -1350,6 +1330,12 @@ void QXcbWindow::setWindowIcon(const QIcon &icon) + } + + if (!icon_data.isEmpty()) { ++ // Ignore icon exceeding maximum xcb request length ++ if (icon_data.size() > xcb_get_maximum_request_length(xcb_connection())) { ++ qWarning("Ignoring window icon: Size %llu exceeds maximum xcb request length %u.", ++ icon_data.size(), xcb_get_maximum_request_length(xcb_connection())); ++ return; ++ } + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, +@@ -1639,7 +1625,7 @@ void QXcbWindow::setWmWindowType(QXcbWindowFunctions::WmWindowTypes types, Qt::W + break; + } + +- if ((flags & Qt::FramelessWindowHint) && !(type & QXcbWindowFunctions::KdeOverride)) { ++ if ((flags & Qt::FramelessWindowHint) && !(types & QXcbWindowFunctions::KdeOverride)) { + // override netwm type - quick and easy for KDE noborder + atoms.append(atom(QXcbAtom::_KDE_NET_WM_WINDOW_TYPE_OVERRIDE)); + } +@@ -1894,10 +1880,6 @@ void QXcbWindow::handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event) + if (event->window == m_window) { + m_mapped = false; + QWindowSystemInterface::handleExposeEvent(window(), QRegion()); +- if (!m_isWmManagedWindow || parent()) { +- m_wmStateValid = true; +- handleDeferredTasks(); +- } + } + } + +@@ -2212,98 +2194,30 @@ void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event) + handleLeaveNotifyEvent(event->root_x, event->root_y, event->mode, event->detail, event->time); + } + +-bool QXcbWindow::shouldDeferTask(Task task) +-{ +- if (m_wmStateValid) +- return false; +- +- m_deferredTasks.append(task); +- return true; +-} +- +-void QXcbWindow::handleDeferredTasks() +-{ +- Q_ASSERT(m_wmStateValid == true); +- if (m_deferredTasks.isEmpty()) +- return; +- +- bool map = false; +- bool unmap = false; +- +- QVector tasks; +- for (auto taskIt = m_deferredTasks.rbegin(); taskIt != m_deferredTasks.rend(); ++taskIt) { +- if (!tasks.contains(*taskIt)) +- tasks.prepend(*taskIt); +- } +- +- for (Task task : tasks) { +- switch (task) { +- case Task::Map: +- map = true; +- unmap = false; +- break; +- case Task::Unmap: +- unmap = true; +- map = false; +- break; +- case Task::SetGeometry: +- setGeometry(m_deferredGeometry); +- break; +- case Task::SetWindowFlags: +- setWindowFlags(window()->flags()); +- break; +- case Task::SetWindowState: +- setWindowState(window()->windowState()); +- break; +- } +- } +- m_deferredTasks.clear(); +- +- if (map) { +- Q_ASSERT(unmap == false); +- show(); +- } +- if (unmap) { +- Q_ASSERT(map == false); +- hide(); +- } +-} +- + void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) + { + connection()->setTime(event->time); + +- const bool wmStateChanged = event->atom == atom(QXcbAtom::WM_STATE); +- const bool netWmStateChanged = event->atom == atom(QXcbAtom::_NET_WM_STATE); +- if (netWmStateChanged || wmStateChanged) { +- if (wmStateChanged && !m_wmStateValid && m_isWmManagedWindow) { +- // ICCCM 4.1.4 +- // Clients that want to re-use a client window (e.g. by mapping it again) +- // after withdrawing it must wait for the withdrawal to be complete before +- // proceeding. The preferred method for doing this is for clients to wait for +- // a window manager to update or remove the WM_STATE property. +- m_wmStateValid = true; +- handleDeferredTasks(); +- } +- if (event->state == XCB_PROPERTY_DELETE) ++ const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE; ++ ++ if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) { ++ if (propertyDeleted) + return; + +- if (wmStateChanged) { ++ Qt::WindowStates newState = Qt::WindowNoState; ++ ++ if (event->atom == atom(QXcbAtom::WM_STATE)) { // WM_STATE: Quick check for 'Minimize'. + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), + 0, m_window, atom(QXcbAtom::WM_STATE), + XCB_ATOM_ANY, 0, 1024); + if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::WM_STATE)) { +- auto data = static_cast(xcb_get_property_value(reply.get())); +- if (reply->length != 0) { +- const bool changedToWithdrawn = data[0] == XCB_ICCCM_WM_STATE_WITHDRAWN; +- const bool changedToIconic = data[0] == XCB_ICCCM_WM_STATE_ICONIC; +- m_minimized = changedToIconic || (changedToWithdrawn && m_minimized); +- } ++ const quint32 *data = (const quint32 *)xcb_get_property_value(reply.get()); ++ if (reply->length != 0) ++ m_minimized = (data[0] == XCB_ICCCM_WM_STATE_ICONIC ++ || (data[0] == XCB_ICCCM_WM_STATE_WITHDRAWN && m_minimized)); + } + } + +- // _NET_WM_STATE handling +- Qt::WindowStates newState = Qt::WindowNoState; + const NetWmStates states = netWmStates(); + // _NET_WM_STATE_HIDDEN should be set by the Window Manager to indicate that a window would + // not be visible on the screen if its desktop/viewport were active and its coordinates were +@@ -2325,6 +2239,7 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev + if ((m_windowState & Qt::WindowMinimized) && connection()->mouseGrabber() == this) + connection()->setMouseGrabber(nullptr); + } ++ return; + } else if (event->atom == atom(QXcbAtom::_NET_FRAME_EXTENTS)) { + m_dirtyFrameMargins = true; + } +diff --git a/qtbase/src/plugins/platforms/xcb/qxcbwindow.h b/qtbase/src/plugins/platforms/xcb/qxcbwindow.h +index 55af9279b1..6f5c1f5ed9 100644 +--- a/qtbase/src/plugins/platforms/xcb/qxcbwindow.h ++++ b/qtbase/src/plugins/platforms/xcb/qxcbwindow.h +@@ -74,14 +74,6 @@ public: + + Q_DECLARE_FLAGS(NetWmStates, NetWmState) + +- enum Task { +- Map, +- Unmap, +- SetGeometry, +- SetWindowFlags, +- SetWindowState +- }; +- + QXcbWindow(QWindow *window); + ~QXcbWindow(); + +@@ -151,9 +143,6 @@ public: + + QXcbWindow *toWindow() override; + +- bool shouldDeferTask(Task task); +- void handleDeferredTasks(); +- + void handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global, + Qt::KeyboardModifiers modifiers, QEvent::Type type, Qt::MouseEventSource source); + +@@ -292,11 +281,6 @@ protected: + int m_swapInterval = -1; + + qreal m_sizeHintsScaleFactor = 1.0; +- +- bool m_wmStateValid = true; +- QVector m_deferredTasks; +- bool m_isWmManagedWindow = true; +- QRect m_deferredGeometry; + }; + + class QXcbForeignWindow : public QXcbWindow +diff --git a/qtbase/src/plugins/platformthemes/gtk3/qgtk3menu.cpp b/qtbase/src/plugins/platformthemes/gtk3/qgtk3menu.cpp +index d9d117faeb..640b49daa0 100644 +--- a/qtbase/src/plugins/platformthemes/gtk3/qgtk3menu.cpp ++++ b/qtbase/src/plugins/platformthemes/gtk3/qgtk3menu.cpp +@@ -85,6 +85,7 @@ QGtk3MenuItem::QGtk3MenuItem() + m_checkable(false), + m_checked(false), + m_enabled(true), ++ m_exclusive(false), + m_underline(false), + m_invalid(true), + m_menu(nullptr), +diff --git a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp +index 0048bbc1e6..396e7f6d1c 100644 +--- a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp ++++ b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp +@@ -102,15 +102,12 @@ const QDBusArgument &operator >>(const QDBusArgument &arg, QXdgDesktopPortalFile + class QXdgDesktopPortalFileDialogPrivate + { + public: +- QXdgDesktopPortalFileDialogPrivate(QPlatformFileDialogHelper *nativeFileDialog) ++ QXdgDesktopPortalFileDialogPrivate(QPlatformFileDialogHelper *nativeFileDialog, uint fileChooserPortalVersion) + : nativeFileDialog(nativeFileDialog) ++ , fileChooserPortalVersion(fileChooserPortalVersion) + { } + +- WId winId = 0; +- bool directoryMode = false; +- bool modal = false; +- bool multipleFiles = false; +- bool saveFile = false; ++ QEventLoop loop; + QString acceptLabel; + QString directory; + QString title; +@@ -121,19 +118,27 @@ public: + QString selectedMimeTypeFilter; + QString selectedNameFilter; + QStringList selectedFiles; +- QPlatformFileDialogHelper *nativeFileDialog = nullptr; ++ std::unique_ptr nativeFileDialog; ++ uint fileChooserPortalVersion = 0; ++ bool failedToOpen = false; ++ bool directoryMode = false; ++ bool multipleFiles = false; ++ bool saveFile = false; + }; + +-QXdgDesktopPortalFileDialog::QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog) ++QXdgDesktopPortalFileDialog::QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog, uint fileChooserPortalVersion) + : QPlatformFileDialogHelper() +- , d_ptr(new QXdgDesktopPortalFileDialogPrivate(nativeFileDialog)) ++ , d_ptr(new QXdgDesktopPortalFileDialogPrivate(nativeFileDialog, fileChooserPortalVersion)) + { + Q_D(QXdgDesktopPortalFileDialog); + + if (d->nativeFileDialog) { +- connect(d->nativeFileDialog, SIGNAL(accept()), this, SIGNAL(accept())); +- connect(d->nativeFileDialog, SIGNAL(reject()), this, SIGNAL(reject())); ++ connect(d->nativeFileDialog.get(), SIGNAL(accept()), this, SIGNAL(accept())); ++ connect(d->nativeFileDialog.get(), SIGNAL(reject()), this, SIGNAL(reject())); + } ++ ++ d->loop.connect(this, SIGNAL(accept()), SLOT(quit())); ++ d->loop.connect(this, SIGNAL(reject()), SLOT(quit())); + } + + QXdgDesktopPortalFileDialog::~QXdgDesktopPortalFileDialog() +@@ -177,7 +182,7 @@ void QXdgDesktopPortalFileDialog::initializeDialog() + setDirectory(options()->initialDirectory()); + } + +-void QXdgDesktopPortalFileDialog::openPortal() ++void QXdgDesktopPortalFileDialog::openPortal(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) + { + Q_D(QXdgDesktopPortalFileDialog); + +@@ -185,13 +190,13 @@ void QXdgDesktopPortalFileDialog::openPortal() + QLatin1String("/org/freedesktop/portal/desktop"), + QLatin1String("org.freedesktop.portal.FileChooser"), + d->saveFile ? QLatin1String("SaveFile") : QLatin1String("OpenFile")); +- QString parentWindowId = QLatin1String("x11:") + QString::number(d->winId, 16); ++ QString parentWindowId = QLatin1String("x11:") + QString::number(parent ? parent->winId() : 0, 16); + + QVariantMap options; + if (!d->acceptLabel.isEmpty()) + options.insert(QLatin1String("accept_label"), d->acceptLabel); + +- options.insert(QLatin1String("modal"), d->modal); ++ options.insert(QLatin1String("modal"), windowModality != Qt::NonModal); + options.insert(QLatin1String("multiple"), d->multipleFiles); + options.insert(QLatin1String("directory"), d->directoryMode); + +@@ -290,10 +295,18 @@ void QXdgDesktopPortalFileDialog::openPortal() + + QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall); +- connect(watcher, &QDBusPendingCallWatcher::finished, this, [this] (QDBusPendingCallWatcher *watcher) { ++ connect(watcher, &QDBusPendingCallWatcher::finished, this, [=] (QDBusPendingCallWatcher *watcher) { + QDBusPendingReply reply = *watcher; +- if (reply.isError()) { +- Q_EMIT reject(); ++ // Any error means the dialog is not shown and we need to fallback ++ d->failedToOpen = reply.isError(); ++ if (d->failedToOpen) { ++ if (d->nativeFileDialog) { ++ d->nativeFileDialog->show(windowFlags, windowModality, parent); ++ if (d->loop.isRunning()) ++ d->nativeFileDialog->exec(); ++ } else { ++ Q_EMIT reject(); ++ } + } else { + QDBusConnection::sessionBus().connect(nullptr, + reply.value().path(), +@@ -302,6 +315,7 @@ void QXdgDesktopPortalFileDialog::openPortal() + this, + SLOT(gotResponse(uint,QVariantMap))); + } ++ watcher->deleteLater(); + }); + } + +@@ -326,7 +340,7 @@ QUrl QXdgDesktopPortalFileDialog::directory() const + { + Q_D(const QXdgDesktopPortalFileDialog); + +- if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly)) ++ if (d->nativeFileDialog && useNativeFileDialog()) + return d->nativeFileDialog->directory(); + + return d->directory; +@@ -348,7 +362,7 @@ QList QXdgDesktopPortalFileDialog::selectedFiles() const + { + Q_D(const QXdgDesktopPortalFileDialog); + +- if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly)) ++ if (d->nativeFileDialog && useNativeFileDialog()) + return d->nativeFileDialog->selectedFiles(); + + QList files; +@@ -403,16 +417,13 @@ void QXdgDesktopPortalFileDialog::exec() + { + Q_D(QXdgDesktopPortalFileDialog); + +- if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly)) { ++ if (d->nativeFileDialog && useNativeFileDialog()) { + d->nativeFileDialog->exec(); + return; + } + + // HACK we have to avoid returning until we emit that the dialog was accepted or rejected +- QEventLoop loop; +- loop.connect(this, SIGNAL(accept()), SLOT(quit())); +- loop.connect(this, SIGNAL(reject()), SLOT(quit())); +- loop.exec(); ++ d->loop.exec(); + } + + void QXdgDesktopPortalFileDialog::hide() +@@ -429,13 +440,10 @@ bool QXdgDesktopPortalFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowMo + + initializeDialog(); + +- d->modal = windowModality != Qt::NonModal; +- d->winId = parent ? parent->winId() : 0; +- +- if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly)) ++ if (d->nativeFileDialog && useNativeFileDialog(OpenFallback)) + return d->nativeFileDialog->show(windowFlags, windowModality, parent); + +- openPortal(); ++ openPortal(windowFlags, windowModality, parent); + + return true; + } +@@ -465,4 +473,21 @@ void QXdgDesktopPortalFileDialog::gotResponse(uint response, const QVariantMap & + } + } + ++bool QXdgDesktopPortalFileDialog::useNativeFileDialog(QXdgDesktopPortalFileDialog::FallbackType fallbackType) const ++{ ++ Q_D(const QXdgDesktopPortalFileDialog); ++ ++ if (d->failedToOpen && fallbackType != OpenFallback) ++ return true; ++ ++ if (d->fileChooserPortalVersion < 3) { ++ if (options()->fileMode() == QFileDialogOptions::Directory) ++ return true; ++ else if (options()->fileMode() == QFileDialogOptions::DirectoryOnly) ++ return true; ++ } ++ ++ return false; ++} ++ + QT_END_NAMESPACE +diff --git a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h +index 4f4de96ecf..65e22a5cf2 100644 +--- a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h ++++ b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h +@@ -51,6 +51,11 @@ class QXdgDesktopPortalFileDialog : public QPlatformFileDialogHelper + Q_OBJECT + Q_DECLARE_PRIVATE(QXdgDesktopPortalFileDialog) + public: ++ enum FallbackType { ++ GenericFallback, ++ OpenFallback ++ }; ++ + enum ConditionType : uint { + GlobalPattern = 0, + MimeType = 1 +@@ -69,7 +74,7 @@ public: + }; + typedef QVector FilterList; + +- QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog = nullptr); ++ QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog = nullptr, uint fileChooserPortalVersion = 0); + ~QXdgDesktopPortalFileDialog(); + + bool defaultNameFilterDisables() const override; +@@ -92,7 +97,8 @@ private Q_SLOTS: + + private: + void initializeDialog(); +- void openPortal(); ++ void openPortal(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent); ++ bool useNativeFileDialog(FallbackType fallbackType = GenericFallback) const; + + QScopedPointer d_ptr; + }; +diff --git a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp +index fb324afbd8..b809503122 100644 +--- a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp ++++ b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp +@@ -111,6 +111,7 @@ QXdgDesktopPortalTheme::QXdgDesktopPortalTheme() + if (reply.isValid()) { + d->fileChooserPortalVersion = reply.value().toUInt(); + } ++ watcher->deleteLater(); + }); + } + +@@ -152,11 +153,12 @@ QPlatformDialogHelper* QXdgDesktopPortalTheme::createPlatformDialogHelper(Dialog + { + Q_D(const QXdgDesktopPortalTheme); + +- if (type == FileDialog) { ++ if (type == FileDialog && d->fileChooserPortalVersion) { + // Older versions of FileChooser portal don't support opening directories, therefore we fallback + // to native file dialog opened inside the sandbox to open a directory. +- if (d->fileChooserPortalVersion < 3 && d->baseTheme->usePlatformNativeDialog(type)) +- return new QXdgDesktopPortalFileDialog(static_cast(d->baseTheme->createPlatformDialogHelper(type))); ++ if (d->baseTheme->usePlatformNativeDialog(type)) ++ return new QXdgDesktopPortalFileDialog(static_cast(d->baseTheme->createPlatformDialogHelper(type)), ++ d->fileChooserPortalVersion); + + return new QXdgDesktopPortalFileDialog; + } +diff --git a/qtbase/src/plugins/printsupport/cups/qcupsprintengine.cpp b/qtbase/src/plugins/printsupport/cups/qcupsprintengine.cpp +index 43d5e119ad..1f9cbc4565 100644 +--- a/qtbase/src/plugins/printsupport/cups/qcupsprintengine.cpp ++++ b/qtbase/src/plugins/printsupport/cups/qcupsprintengine.cpp +@@ -89,8 +89,10 @@ void QCupsPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &v + break; + case PPK_Duplex: { + QPrint::DuplexMode mode = QPrint::DuplexMode(value.toInt()); +- if (mode != d->duplex && d->m_printDevice.supportedDuplexModes().contains(mode)) ++ if (d->m_printDevice.supportedDuplexModes().contains(mode)) { + d->duplex = mode; ++ d->duplexRequestedExplicitly = true; ++ } + break; + } + case PPK_PrinterName: +@@ -277,9 +279,12 @@ void QCupsPrintEnginePrivate::changePrinter(const QString &newPrinter) + m_printDevice.swap(printDevice); + printerName = m_printDevice.id(); + +- // Check if new printer supports current settings, otherwise us defaults +- if (duplex != QPrint::DuplexAuto && !m_printDevice.supportedDuplexModes().contains(duplex)) ++ // in case a duplex value was explicitly set, check if new printer supports current value, ++ // otherwise use device default ++ if (!duplexRequestedExplicitly || !m_printDevice.supportedDuplexModes().contains(duplex)) { + duplex = m_printDevice.defaultDuplexMode(); ++ duplexRequestedExplicitly = false; ++ } + QPrint::ColorMode colorMode = grayscale ? QPrint::GrayScale : QPrint::Color; + if (!m_printDevice.supportedColorModes().contains(colorMode)) + grayscale = m_printDevice.defaultColorMode() == QPrint::GrayScale; +diff --git a/qtbase/src/plugins/printsupport/cups/qcupsprintengine_p.h b/qtbase/src/plugins/printsupport/cups/qcupsprintengine_p.h +index c021b0c643..8f81fe478d 100644 +--- a/qtbase/src/plugins/printsupport/cups/qcupsprintengine_p.h ++++ b/qtbase/src/plugins/printsupport/cups/qcupsprintengine_p.h +@@ -100,6 +100,7 @@ private: + QStringList cupsOptions; + QString cupsTempFile; + QPrint::DuplexMode duplex; ++ bool duplexRequestedExplicitly = false; + }; + + QT_END_NAMESPACE +diff --git a/qtbase/src/plugins/sqldrivers/ibase/qsql_ibase.cpp b/qtbase/src/plugins/sqldrivers/ibase/qsql_ibase.cpp +index 67e7154fa6..40876152e5 100644 +--- a/qtbase/src/plugins/sqldrivers/ibase/qsql_ibase.cpp ++++ b/qtbase/src/plugins/sqldrivers/ibase/qsql_ibase.cpp +@@ -817,7 +817,7 @@ bool QIBaseResultPrivate::writeArray(int column, const QList &list) + ba.resize(int(bufLen)); + + if (list.size() > arraySize) { +- error = QLatin1String("Array size missmatch: size of %1 is %2, size of provided list is %3"); ++ error = QLatin1String("Array size mismatch: size of %1 is %2, size of provided list is %3"); + error = error.arg(QLatin1String(sqlname)).arg(arraySize).arg(list.size()); + q->setLastError(QSqlError(error, QLatin1String(""), QSqlError::StatementError)); + return false; +diff --git a/qtbase/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/qtbase/src/plugins/sqldrivers/mysql/qsql_mysql.cpp +index 7ca055eea2..6bc9d46755 100644 +--- a/qtbase/src/plugins/sqldrivers/mysql/qsql_mysql.cpp ++++ b/qtbase/src/plugins/sqldrivers/mysql/qsql_mysql.cpp +@@ -223,7 +223,7 @@ public: + struct QMyField + { + char *outField = nullptr; +- MYSQL_FIELD *myField = nullptr; ++ const MYSQL_FIELD *myField = nullptr; + QMetaType::Type type = QMetaType::UnknownType; + my_bool nullIndicator = false; + ulong bufLength = 0ul; +@@ -361,7 +361,7 @@ static bool qIsInteger(int t) + void QMYSQLResultPrivate::bindBlobs() + { + int i; +- MYSQL_FIELD *fieldInfo; ++ const MYSQL_FIELD *fieldInfo; + MYSQL_BIND *bind; + + for(i = 0; i < fields.count(); ++i) { +@@ -379,7 +379,6 @@ void QMYSQLResultPrivate::bindBlobs() + bool QMYSQLResultPrivate::bindInValues() + { + MYSQL_BIND *bind; +- char *field; + int i = 0; + + if (!meta) +@@ -392,35 +391,34 @@ bool QMYSQLResultPrivate::bindInValues() + inBinds = new MYSQL_BIND[fields.size()]; + memset(inBinds, 0, fields.size() * sizeof(MYSQL_BIND)); + +- MYSQL_FIELD *fieldInfo; ++ const MYSQL_FIELD *fieldInfo; + + while((fieldInfo = mysql_fetch_field(meta))) { ++ bind = &inBinds[i]; ++ + QMyField &f = fields[i]; + f.myField = fieldInfo; +- ++ bind->buffer_length = f.bufLength = fieldInfo->length + 1; ++ bind->buffer_type = fieldInfo->type; + f.type = qDecodeMYSQLType(fieldInfo->type, fieldInfo->flags); + if (qIsBlob(fieldInfo->type)) { + // the size of a blob-field is available as soon as we call + // mysql_stmt_store_result() + // after mysql_stmt_exec() in QMYSQLResult::exec() +- fieldInfo->length = 0; ++ bind->buffer_length = f.bufLength = 0; + hasBlobs = true; + } else if (qIsInteger(f.type)) { +- fieldInfo->length = 8; ++ bind->buffer_length = f.bufLength = 8; + } else { +- fieldInfo->type = MYSQL_TYPE_STRING; ++ bind->buffer_type = MYSQL_TYPE_STRING; + } +- bind = &inBinds[i]; +- field = new char[fieldInfo->length + 1]; +- memset(field, 0, fieldInfo->length + 1); + +- bind->buffer_type = fieldInfo->type; +- bind->buffer = field; +- bind->buffer_length = f.bufLength = fieldInfo->length + 1; + bind->is_null = &f.nullIndicator; + bind->length = &f.bufLength; + bind->is_unsigned = fieldInfo->flags & UNSIGNED_FLAG ? 1 : 0; +- f.outField=field; ++ ++ char *field = new char[bind->buffer_length + 1]{}; ++ bind->buffer = f.outField = field; + + ++i; + } +@@ -1369,20 +1367,20 @@ bool QMYSQLDriver::open(const QString& db, + } + + #if MYSQL_VERSION_ID >= 50007 +- if (mysql_get_client_version() >= 50503 && mysql_get_server_version(d->mysql) >= 50503) { +- // force the communication to be utf8mb4 (only utf8mb4 supports 4-byte characters) +- mysql_set_character_set(d->mysql, "utf8mb4"); ++ // force the communication to be utf8mb4 (only utf8mb4 supports 4-byte characters) ++ if (mysql_set_character_set(d->mysql, "utf8mb4")) { ++ // this failed, try forcing it to utf (BMP only) ++ if (mysql_set_character_set(d->mysql, "utf8")) ++ qWarning() << "MySQL: Unable to set the client character set to utf8."; + #if QT_CONFIG(textcodec) +- d->tc = QTextCodec::codecForName("UTF-8"); ++ else ++ d->tc = codec(d->mysql); + #endif +- } else +- { +- // force the communication to be utf8 +- mysql_set_character_set(d->mysql, "utf8"); ++ } + #if QT_CONFIG(textcodec) +- d->tc = codec(d->mysql); ++ else ++ d->tc = QTextCodec::codecForName("UTF-8"); + #endif +- } + #endif // MYSQL_VERSION_ID >= 50007 + + d->preparedQuerysEnabled = checkPreparedQueries(d->mysql); +diff --git a/qtbase/src/printsupport/dialogs/images/print-24.png b/qtbase/src/printsupport/dialogs/images/printer-24.png +similarity index 100% +rename from src/printsupport/dialogs/images/print-24.png +rename to src/printsupport/dialogs/images/printer-24.png +diff --git a/qtbase/src/printsupport/dialogs/images/print-32.png b/qtbase/src/printsupport/dialogs/images/printer-32.png +similarity index 100% +rename from src/printsupport/dialogs/images/print-32.png +rename to src/printsupport/dialogs/images/printer-32.png +diff --git a/qtbase/src/printsupport/dialogs/images/view-page-sided-24.png b/qtbase/src/printsupport/dialogs/images/view-pages-facing-24.png +similarity index 100% +rename from src/printsupport/dialogs/images/view-page-sided-24.png +rename to src/printsupport/dialogs/images/view-pages-facing-24.png +diff --git a/qtbase/src/printsupport/dialogs/images/view-page-sided-32.png b/qtbase/src/printsupport/dialogs/images/view-pages-facing-32.png +similarity index 100% +rename from src/printsupport/dialogs/images/view-page-sided-32.png +rename to src/printsupport/dialogs/images/view-pages-facing-32.png +diff --git a/qtbase/src/printsupport/dialogs/images/view-page-multi-24.png b/qtbase/src/printsupport/dialogs/images/view-pages-overview-24.png +similarity index 100% +rename from src/printsupport/dialogs/images/view-page-multi-24.png +rename to src/printsupport/dialogs/images/view-pages-overview-24.png +diff --git a/qtbase/src/printsupport/dialogs/images/view-page-multi-32.png b/qtbase/src/printsupport/dialogs/images/view-pages-overview-32.png +similarity index 100% +rename from src/printsupport/dialogs/images/view-page-multi-32.png +rename to src/printsupport/dialogs/images/view-pages-overview-32.png +diff --git a/qtbase/src/printsupport/dialogs/images/view-page-one-24.png b/qtbase/src/printsupport/dialogs/images/view-pages-single-24.png +similarity index 100% +rename from src/printsupport/dialogs/images/view-page-one-24.png +rename to src/printsupport/dialogs/images/view-pages-single-24.png +diff --git a/qtbase/src/printsupport/dialogs/images/view-page-one-32.png b/qtbase/src/printsupport/dialogs/images/view-pages-single-32.png +similarity index 100% +rename from src/printsupport/dialogs/images/view-page-one-32.png +rename to src/printsupport/dialogs/images/view-pages-single-32.png +diff --git a/qtbase/src/printsupport/dialogs/images/fit-page-24.png b/qtbase/src/printsupport/dialogs/images/zoom-fit-page-24.png +similarity index 100% +rename from src/printsupport/dialogs/images/fit-page-24.png +rename to src/printsupport/dialogs/images/zoom-fit-page-24.png +diff --git a/qtbase/src/printsupport/dialogs/images/fit-page-32.png b/qtbase/src/printsupport/dialogs/images/zoom-fit-page-32.png +similarity index 100% +rename from src/printsupport/dialogs/images/fit-page-32.png +rename to src/printsupport/dialogs/images/zoom-fit-page-32.png +diff --git a/qtbase/src/printsupport/dialogs/images/fit-width-24.png b/qtbase/src/printsupport/dialogs/images/zoom-fit-width-24.png +similarity index 100% +rename from src/printsupport/dialogs/images/fit-width-24.png +rename to src/printsupport/dialogs/images/zoom-fit-width-24.png +diff --git a/qtbase/src/printsupport/dialogs/images/fit-width-32.png b/qtbase/src/printsupport/dialogs/images/zoom-fit-width-32.png +similarity index 100% +rename from src/printsupport/dialogs/images/fit-width-32.png +rename to src/printsupport/dialogs/images/zoom-fit-width-32.png +diff --git a/qtbase/src/printsupport/dialogs/qpagesetupdialog_unix.cpp b/qtbase/src/printsupport/dialogs/qpagesetupdialog_unix.cpp +index 78e5b8d1ef..2a28516719 100644 +--- a/qtbase/src/printsupport/dialogs/qpagesetupdialog_unix.cpp ++++ b/qtbase/src/printsupport/dialogs/qpagesetupdialog_unix.cpp +@@ -532,6 +532,7 @@ void QPageSetupWidget::updateWidget() + void QPageSetupWidget::setupPrinter() const + { + m_printer->setPageLayout(m_pageLayout); ++ m_printer->setPageOrientation(m_pageLayout.orientation()); + #if QT_CONFIG(cups) + QCUPSSupport::PagesPerSheet pagesPerSheet = qvariant_cast(m_ui.pagesPerSheetCombo->currentData() + ); +diff --git a/qtbase/src/printsupport/dialogs/qprintdialog.qrc b/qtbase/src/printsupport/dialogs/qprintdialog.qrc +index 5a579baa55..10b8e1d341 100644 +--- a/qtbase/src/printsupport/dialogs/qprintdialog.qrc ++++ b/qtbase/src/printsupport/dialogs/qprintdialog.qrc +@@ -1,9 +1,9 @@ + + +-images/fit-page-24.png +-images/fit-page-32.png +-images/fit-width-24.png +-images/fit-width-32.png ++images/zoom-fit-page-24.png ++images/zoom-fit-page-32.png ++images/zoom-fit-width-24.png ++images/zoom-fit-width-32.png + images/go-first-24.png + images/go-first-32.png + images/go-last-24.png +@@ -18,14 +18,14 @@ + images/layout-portrait-32.png + images/page-setup-24.png + images/page-setup-32.png +-images/print-24.png +-images/print-32.png +-images/view-page-multi-24.png +-images/view-page-multi-32.png +-images/view-page-one-24.png +-images/view-page-one-32.png +-images/view-page-sided-24.png +-images/view-page-sided-32.png ++images/printer-24.png ++images/printer-32.png ++images/view-pages-overview-24.png ++images/view-pages-overview-32.png ++images/view-pages-single-24.png ++images/view-pages-single-32.png ++images/view-pages-facing-24.png ++images/view-pages-facing-32.png + images/zoom-in-24.png + images/zoom-in-32.png + images/zoom-out-24.png +diff --git a/qtbase/src/printsupport/dialogs/qprintdialog_unix.cpp b/qtbase/src/printsupport/dialogs/qprintdialog_unix.cpp +index c5b845f4ec..5a5ba1d0a8 100644 +--- a/qtbase/src/printsupport/dialogs/qprintdialog_unix.cpp ++++ b/qtbase/src/printsupport/dialogs/qprintdialog_unix.cpp +@@ -702,13 +702,14 @@ void QPrintDialogPrivate::selectPrinter(const QPrinter::OutputFormat outputForma + else + options.grayscale->setChecked(true); + +- // keep duplex value explicitly set by user, if any, and selected printer supports it; +- // use device default otherwise ++ // duplex priorities to be as follows: ++ // 1) a user-selected duplex value in the dialog has highest prority ++ // 2) duplex value set in the QPrinter + QPrint::DuplexMode duplex; + if (explicitDuplexMode != QPrint::DuplexAuto && supportedDuplexMode.contains(explicitDuplexMode)) + duplex = explicitDuplexMode; + else +- duplex = top->d->m_currentPrintDevice.defaultDuplexMode(); ++ duplex = static_cast(p->duplex()); + switch (duplex) { + case QPrint::DuplexNone: + options.noDuplex->setChecked(true); break; +@@ -1242,10 +1243,10 @@ void QUnixPrintWidgetPrivate::_q_printerChanged(int index) + QString filename = widget.filename->text(); + widget.filename->setText(filename); + widget.lOutput->setEnabled(true); +- if (optionsPane) +- optionsPane->selectPrinter(QPrinter::PdfFormat); + printer->setOutputFormat(QPrinter::PdfFormat); + m_currentPrintDevice = QPrintDevice(); ++ if (optionsPane) ++ optionsPane->selectPrinter(QPrinter::PdfFormat); + return; + } + } +diff --git a/qtbase/src/printsupport/dialogs/qprintpreviewdialog.cpp b/qtbase/src/printsupport/dialogs/qprintpreviewdialog.cpp +index 39575d5f57..23b7e89538 100644 +--- a/qtbase/src/printsupport/dialogs/qprintpreviewdialog.cpp ++++ b/qtbase/src/printsupport/dialogs/qprintpreviewdialog.cpp +@@ -352,7 +352,7 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer) + static inline void qt_setupActionIcon(QAction *action, QLatin1String name) + { + QLatin1String imagePrefix(":/qt-project.org/dialogs/qprintpreviewdialog/images/"); +- QIcon icon; ++ QIcon icon = QIcon::fromTheme(name); + icon.addFile(imagePrefix + name + QLatin1String("-24.png"), QSize(24, 24)); + icon.addFile(imagePrefix + name + QLatin1String("-32.png"), QSize(32, 32)); + action->setIcon(icon); +@@ -383,8 +383,8 @@ void QPrintPreviewDialogPrivate::setupActions() + fitPageAction->setObjectName(QLatin1String("fitPageAction")); + fitWidthAction->setCheckable(true); + fitPageAction->setCheckable(true); +- qt_setupActionIcon(fitWidthAction, QLatin1String("fit-width")); +- qt_setupActionIcon(fitPageAction, QLatin1String("fit-page")); ++ qt_setupActionIcon(fitWidthAction, QLatin1String("zoom-fit-width")); ++ qt_setupActionIcon(fitPageAction, QLatin1String("zoom-fit-page")); + QObject::connect(fitGroup, SIGNAL(triggered(QAction*)), q, SLOT(_q_fit(QAction*))); + + // Zoom +@@ -410,9 +410,9 @@ void QPrintPreviewDialogPrivate::setupActions() + singleModeAction = modeGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Show single page")); + facingModeAction = modeGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Show facing pages")); + overviewModeAction = modeGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Show overview of all pages")); +- qt_setupActionIcon(singleModeAction, QLatin1String("view-page-one")); +- qt_setupActionIcon(facingModeAction, QLatin1String("view-page-sided")); +- qt_setupActionIcon(overviewModeAction, QLatin1String("view-page-multi")); ++ qt_setupActionIcon(singleModeAction, QLatin1String("view-pages-single")); ++ qt_setupActionIcon(facingModeAction, QLatin1String("view-pages-facing")); ++ qt_setupActionIcon(overviewModeAction, QLatin1String("view-pages-overview")); + singleModeAction->setObjectName(QLatin1String("singleModeAction")); + facingModeAction->setObjectName(QLatin1String("facingModeAction")); + overviewModeAction->setObjectName(QLatin1String("overviewModeAction")); +@@ -426,7 +426,7 @@ void QPrintPreviewDialogPrivate::setupActions() + printerGroup = new QActionGroup(q); + printAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Print")); + pageSetupAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Page setup")); +- qt_setupActionIcon(printAction, QLatin1String("print")); ++ qt_setupActionIcon(printAction, QLatin1String("printer")); + qt_setupActionIcon(pageSetupAction, QLatin1String("page-setup")); + QObject::connect(printAction, SIGNAL(triggered(bool)), q, SLOT(_q_print())); + QObject::connect(pageSetupAction, SIGNAL(triggered(bool)), q, SLOT(_q_pageSetup())); +diff --git a/qtbase/src/sql/kernel/qsqlquery.cpp b/qtbase/src/sql/kernel/qsqlquery.cpp +index 32c6166c79..60afef10c3 100644 +--- a/qtbase/src/sql/kernel/qsqlquery.cpp ++++ b/qtbase/src/sql/kernel/qsqlquery.cpp +@@ -1,6 +1,6 @@ + /**************************************************************************** + ** +-** Copyright (C) 2016 The Qt Company Ltd. ++** Copyright (C) 2022 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the QtSql module of the Qt Toolkit. +@@ -377,6 +377,10 @@ bool QSqlQuery::exec(const QString& query) + QElapsedTimer t; + t.start(); + #endif ++ if (!driver()) { ++ qWarning("QSqlQuery::exec: called before driver has been set up"); ++ return false; ++ } + if (d->ref.loadRelaxed() != 1) { + bool fo = isForwardOnly(); + *this = QSqlQuery(driver()->createResult()); +diff --git a/qtbase/src/testlib/qabstractitemmodeltester.cpp b/qtbase/src/testlib/qabstractitemmodeltester.cpp +index 8efb9c53d4..ce062f66d7 100644 +--- a/qtbase/src/testlib/qabstractitemmodeltester.cpp ++++ b/qtbase/src/testlib/qabstractitemmodeltester.cpp +@@ -454,7 +454,7 @@ void QAbstractItemModelTesterPrivate::parent() + + // Common error test #2, make sure that a second level index has a parent + // that is the first level index. +- if (model->rowCount(topIndex) > 0) { ++ if (model->rowCount(topIndex) > 0 && model->columnCount(topIndex) > 0) { + QModelIndex childIndex = model->index(0, 0, topIndex); + MODELTESTER_VERIFY(childIndex.isValid()); + MODELTESTER_COMPARE(model->parent(childIndex), topIndex); +diff --git a/qtbase/src/testlib/qasciikey.cpp b/qtbase/src/testlib/qasciikey.cpp +index 9a308da2bc..93498b256f 100644 +--- a/qtbase/src/testlib/qasciikey.cpp ++++ b/qtbase/src/testlib/qasciikey.cpp +@@ -498,6 +498,11 @@ char QTest::keyToAscii(Qt::Key key) + case Qt::Key_LaunchE : return 0; // = 0x10b0, + case Qt::Key_LaunchF : return 0; // = 0x10b1, + ++ // Keypad navigation keys ++ case Qt::Key_Select : return 0; // = 0x01010000 ++ case Qt::Key_Yes : return 0; // = 0x01010001 ++ case Qt::Key_No : return 0; // = 0x01010002 ++ + default: QTEST_ASSERT(false); return 0; + } + } +diff --git a/qtbase/src/testlib/qtestresult.cpp b/qtbase/src/testlib/qtestresult.cpp +index 88028aac6e..2e89930776 100644 +--- a/qtbase/src/testlib/qtestresult.cpp ++++ b/qtbase/src/testlib/qtestresult.cpp +@@ -251,7 +251,8 @@ bool QTestResult::verify(bool statement, const char *statementStr, + { + QTEST_ASSERT(statementStr); + +- char msg[1024] = {'\0'}; ++ char msg[1024]; ++ msg[0] = '\0'; + + if (QTestLog::verboseLevel() >= 2) { + qsnprintf(msg, 1024, "QVERIFY(%s)", statementStr); +@@ -309,7 +310,8 @@ static bool compareHelper(bool success, const char *failureMsg, + bool hasValues = true) + { + const size_t maxMsgLen = 1024; +- char msg[maxMsgLen] = {'\0'}; ++ char msg[maxMsgLen]; ++ msg[0] = '\0'; + + QTEST_ASSERT(expected); + QTEST_ASSERT(actual); +diff --git a/qtbase/src/widgets/dialogs/qcolordialog.cpp b/qtbase/src/widgets/dialogs/qcolordialog.cpp +index 4247731275..cb325be85c 100644 +--- a/qtbase/src/widgets/dialogs/qcolordialog.cpp ++++ b/qtbase/src/widgets/dialogs/qcolordialog.cpp +@@ -78,7 +78,10 @@ + #include "qwindow.h" + + #include "private/qdialog_p.h" ++#include "private/qguiapplication_p.h" + ++#include ++#include + #include + + QT_BEGIN_NAMESPACE +@@ -1611,6 +1614,20 @@ void QColorDialogPrivate::_q_newStandard(int r, int c) + void QColorDialogPrivate::_q_pickScreenColor() + { + Q_Q(QColorDialog); ++ ++ auto *platformServices = QGuiApplicationPrivate::platformIntegration()->services(); ++ if (platformServices->hasCapability(QPlatformServices::Capability::ColorPicking)) { ++ if (auto *colorPicker = platformServices->colorPicker(q->windowHandle())) { ++ q->connect(colorPicker, &QPlatformServiceColorPicker::colorPicked, q, ++ [q, colorPicker](const QColor &color) { ++ colorPicker->deleteLater(); ++ q->setCurrentColor(color); ++ }); ++ colorPicker->pickColor(); ++ return; ++ } ++ } ++ + if (!colorPickingEventFilter) + colorPickingEventFilter = new QColorPickingEventFilter(this, q); + q->installEventFilter(colorPickingEventFilter); +diff --git a/qtbase/src/widgets/itemviews/qabstractitemdelegate.cpp b/qtbase/src/widgets/itemviews/qabstractitemdelegate.cpp +index e120817edc..8ea36b5427 100644 +--- a/qtbase/src/widgets/itemviews/qabstractitemdelegate.cpp ++++ b/qtbase/src/widgets/itemviews/qabstractitemdelegate.cpp +@@ -400,12 +400,7 @@ bool QAbstractItemDelegate::helpEvent(QHelpEvent *event, + const QString tooltip = index.isValid() ? + d->textForRole(Qt::ToolTipRole, index.data(Qt::ToolTipRole), option.locale, precision) : + QString(); +- QRect rect; +- if (index.isValid()) { +- const QRect r = view->visualRect(index); +- rect = QRect(view->mapToGlobal(r.topLeft()), r.size()); +- } +- QToolTip::showText(he->globalPos(), tooltip, view, rect); ++ QToolTip::showText(he->globalPos(), tooltip, view->viewport(), option.rect); + event->setAccepted(!tooltip.isEmpty()); + break; + } +diff --git a/qtbase/src/widgets/itemviews/qlistview.cpp b/qtbase/src/widgets/itemviews/qlistview.cpp +index 2b34476642..eebfaa030e 100644 +--- a/qtbase/src/widgets/itemviews/qlistview.cpp ++++ b/qtbase/src/widgets/itemviews/qlistview.cpp +@@ -3386,6 +3386,7 @@ void QIconModeViewBase::updateContentsSize() + */ + void QListView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) + { ++ QAbstractItemView::currentChanged(current, previous); + #ifndef QT_NO_ACCESSIBILITY + if (QAccessible::isActive()) { + if (current.isValid()) { +@@ -3396,7 +3397,6 @@ void QListView::currentChanged(const QModelIndex ¤t, const QModelIndex &pr + } + } + #endif +- QAbstractItemView::currentChanged(current, previous); + } + + /*! +diff --git a/qtbase/src/widgets/itemviews/qtableview.cpp b/qtbase/src/widgets/itemviews/qtableview.cpp +index 934ac581b2..f79bb24249 100644 +--- a/qtbase/src/widgets/itemviews/qtableview.cpp ++++ b/qtbase/src/widgets/itemviews/qtableview.cpp +@@ -1013,6 +1013,7 @@ void QTableViewPrivate::drawCell(QPainter *painter, const QStyleOptionViewItem & + int QTableViewPrivate::widthHintForIndex(const QModelIndex &index, int hint, const QStyleOptionViewItem &option) const + { + Q_Q(const QTableView); ++ const int oldHint = hint; + QWidget *editor = editorForIndex(index).widget.data(); + if (editor && persistent.contains(editor)) { + hint = qMax(hint, editor->sizeHint().width()); +@@ -1021,6 +1022,17 @@ int QTableViewPrivate::widthHintForIndex(const QModelIndex &index, int hint, con + hint = qBound(min, hint, max); + } + hint = qMax(hint, q->itemDelegate(index)->sizeHint(option, index).width()); ++ ++ if (hasSpans()) { ++ auto span = spans.spanAt(index.column(), index.row()); ++ if (span && span->m_left == index.column() && span->m_top == index.row()) { ++ // spans are screwed up when sections are moved ++ const auto left = logicalColumn(span->m_left); ++ for (int i = 1; i <= span->width(); ++i) ++ hint -= q->columnWidth(visualColumn(left + i)); ++ } ++ hint = std::max(hint, oldHint); ++ } + return hint; + } + +@@ -1053,6 +1065,11 @@ int QTableViewPrivate::heightHintForIndex(const QModelIndex &index, int hint, QS + option.rect.setHeight(height); + option.rect.setX(q->columnViewportPosition(index.column())); + option.rect.setWidth(q->columnWidth(index.column())); ++ if (hasSpans()) { ++ auto span = spans.spanAt(index.column(), index.row()); ++ if (span && span->m_left == index.column() && span->m_top == index.row()) ++ option.rect.setWidth(std::max(option.rect.width(), visualSpanRect(*span).width())); ++ } + // 1px less space when grid is shown (see drawCell) + if (showGrid) + option.rect.setWidth(option.rect.width() - 1); +diff --git a/qtbase/src/widgets/kernel/qaction.h b/qtbase/src/widgets/kernel/qaction.h +index 258a1ea0a0..737c1e8285 100644 +--- a/qtbase/src/widgets/kernel/qaction.h ++++ b/qtbase/src/widgets/kernel/qaction.h +@@ -81,7 +81,7 @@ class Q_WIDGETS_EXPORT QAction : public QObject + Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole NOTIFY changed) + Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu NOTIFY changed) + Q_PROPERTY(bool shortcutVisibleInContextMenu READ isShortcutVisibleInContextMenu WRITE setShortcutVisibleInContextMenu NOTIFY changed) +- Q_PROPERTY(Priority priority READ priority WRITE setPriority) ++ Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY changed) + + public: + // note this is copied into qplatformmenu.h, which must stay in sync +diff --git a/qtbase/src/widgets/kernel/qwidget.cpp b/qtbase/src/widgets/kernel/qwidget.cpp +index 9eba1e001e..26f6d27e18 100644 +--- a/qtbase/src/widgets/kernel/qwidget.cpp ++++ b/qtbase/src/widgets/kernel/qwidget.cpp +@@ -5296,7 +5296,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP + QWidgetEffectSourcePrivate *sourced = static_cast + (source->d_func()); + if (!sourced->context) { +- const QRegion effectRgn(rgn.boundingRect()); ++ const QRegion effectRgn((flags & UseEffectRegionBounds) ? rgn.boundingRect() : rgn); + QWidgetPaintContext context(pdev, effectRgn, offset, flags, sharedPainter, repaintManager); + sourced->context = &context; + if (!sharedPainter) { +@@ -5328,6 +5328,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP + } + } + #endif // QT_CONFIG(graphicseffect) ++ flags = flags & ~UseEffectRegionBounds; + + const bool alsoOnScreen = flags & DrawPaintOnScreen; + const bool recursive = flags & DrawRecursive; +diff --git a/qtbase/src/widgets/kernel/qwidget_p.h b/qtbase/src/widgets/kernel/qwidget_p.h +index eef6b8fa2c..c432f4b5d5 100644 +--- a/qtbase/src/widgets/kernel/qwidget_p.h ++++ b/qtbase/src/widgets/kernel/qwidget_p.h +@@ -229,7 +229,8 @@ public: + DontSubtractOpaqueChildren = 0x10, + DontDrawOpaqueChildren = 0x20, + DontDrawNativeChildren = 0x40, +- DontSetCompositionMode = 0x80 ++ DontSetCompositionMode = 0x80, ++ UseEffectRegionBounds = 0x100 + }; + Q_DECLARE_FLAGS(DrawWidgetFlags, DrawWidgetFlag) + Q_FLAG(DrawWidgetFlags) +diff --git a/qtbase/src/widgets/kernel/qwidgetrepaintmanager.cpp b/qtbase/src/widgets/kernel/qwidgetrepaintmanager.cpp +index 02880b34da..0d44e1326d 100644 +--- a/qtbase/src/widgets/kernel/qwidgetrepaintmanager.cpp ++++ b/qtbase/src/widgets/kernel/qwidgetrepaintmanager.cpp +@@ -1018,7 +1018,8 @@ void QWidgetRepaintManager::paintAndFlush() + + // Paint the rest with composition. + if (repaintAllWidgets || !dirtyCopy.isEmpty()) { +- QWidgetPrivate::DrawWidgetFlags flags = QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawRecursive; ++ QWidgetPrivate::DrawWidgetFlags flags = QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawRecursive ++ | QWidgetPrivate::UseEffectRegionBounds; + tlw->d_func()->drawWidget(store->paintDevice(), dirtyCopy, QPoint(), flags, nullptr, this); + } + +diff --git a/qtbase/src/widgets/styles/qfusionstyle.cpp b/qtbase/src/widgets/styles/qfusionstyle.cpp +index f4345d97c4..962912c838 100644 +--- a/qtbase/src/widgets/styles/qfusionstyle.cpp ++++ b/qtbase/src/widgets/styles/qfusionstyle.cpp +@@ -1772,14 +1772,6 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio + proxy()->drawControl(CE_PushButtonLabel, &subopt, painter, widget); + } + break; +- case CE_PushButtonLabel: +- if (const QStyleOptionButton *button = qstyleoption_cast(option)) { +- QStyleOptionButton b(*button); +- // no PM_ButtonShiftHorizontal and PM_ButtonShiftVertical for fusion style +- b.state &= ~(State_On | State_Sunken); +- QCommonStyle::drawControl(element, &b, painter, widget); +- } +- break; + case CE_MenuBarEmptyArea: + painter->save(); + { +diff --git a/qtbase/src/widgets/util/qcompleter.cpp b/qtbase/src/widgets/util/qcompleter.cpp +index 18b24063d8..ef7207a8a3 100644 +--- a/qtbase/src/widgets/util/qcompleter.cpp ++++ b/qtbase/src/widgets/util/qcompleter.cpp +@@ -1120,6 +1120,8 @@ void QCompleter::setModel(QAbstractItemModel *model) + { + Q_D(QCompleter); + QAbstractItemModel *oldModel = d->proxy->sourceModel(); ++ if (oldModel == model) ++ return; + #if QT_CONFIG(filesystemmodel) + if (qobject_cast(oldModel)) + setCompletionRole(Qt::EditRole); // QTBUG-54642, clear FileNameRole set by QFileSystemModel +diff --git a/qtbase/src/widgets/widgets/qabstractbutton.cpp b/qtbase/src/widgets/widgets/qabstractbutton.cpp +index a128b23950..dc40bf62fb 100644 +--- a/qtbase/src/widgets/widgets/qabstractbutton.cpp ++++ b/qtbase/src/widgets/widgets/qabstractbutton.cpp +@@ -56,6 +56,7 @@ + #ifndef QT_NO_ACCESSIBILITY + #include "qaccessible.h" + #endif ++#include + + #include + +@@ -1076,19 +1077,19 @@ void QAbstractButton::keyPressEvent(QKeyEvent *e) + { + Q_D(QAbstractButton); + bool next = true; +- switch (e->key()) { +- case Qt::Key_Enter: +- case Qt::Key_Return: +- e->ignore(); +- break; +- case Qt::Key_Select: +- case Qt::Key_Space: +- if (!e->isAutoRepeat()) { +- setDown(true); +- repaint(); +- d->emitPressed(); +- } +- break; ++ ++ const auto key = static_cast(e->key()); ++ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() ++ ->themeHint(QPlatformTheme::ButtonPressKeys) ++ .value>(); ++ if (buttonPressKeys.contains(key) && !e->isAutoRepeat()) { ++ setDown(true); ++ repaint(); ++ d->emitPressed(); ++ return; ++ } ++ ++ switch (key) { + case Qt::Key_Up: + next = false; + Q_FALLTHROUGH(); +@@ -1153,15 +1154,15 @@ void QAbstractButton::keyReleaseEvent(QKeyEvent *e) + if (!e->isAutoRepeat()) + d->repeatTimer.stop(); + +- switch (e->key()) { +- case Qt::Key_Select: +- case Qt::Key_Space: +- if (!e->isAutoRepeat() && d->down) +- d->click(); +- break; +- default: +- e->ignore(); ++ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() ++ ->themeHint(QPlatformTheme::ButtonPressKeys) ++ .value>(); ++ if (buttonPressKeys.contains(static_cast(e->key())) && !e->isAutoRepeat() && d->down) { ++ d->click(); ++ return; + } ++ ++ e->ignore(); + } + + /*!\reimp +diff --git a/qtbase/src/widgets/widgets/qcombobox.cpp b/qtbase/src/widgets/widgets/qcombobox.cpp +index 7a496c27e0..0a3d96647b 100644 +--- a/qtbase/src/widgets/widgets/qcombobox.cpp ++++ b/qtbase/src/widgets/widgets/qcombobox.cpp +@@ -3352,7 +3352,23 @@ void QComboBox::keyPressEvent(QKeyEvent *e) + + Move move = NoMove; + int newIndex = currentIndex(); +- switch (e->key()) { ++ ++ bool pressLikeButton = !d->lineEdit; ++#ifdef QT_KEYPAD_NAVIGATION ++ pressLikeButton |= QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus(); ++#endif ++ auto key = static_cast(e->key()); ++ if (pressLikeButton) { ++ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() ++ ->themeHint(QPlatformTheme::ButtonPressKeys) ++ .value>(); ++ if (buttonPressKeys.contains(key)) { ++ showPopup(); ++ return; ++ } ++ } ++ ++ switch (key) { + case Qt::Key_Up: + if (e->modifiers() & Qt::ControlModifier) + break; // pass to line edit for auto completion +@@ -3394,26 +3410,11 @@ void QComboBox::keyPressEvent(QKeyEvent *e) + return; + } + break; +- case Qt::Key_Space: +- if (!d->lineEdit) { +- showPopup(); +- return; +- } +- break; +- case Qt::Key_Enter: +- case Qt::Key_Return: + case Qt::Key_Escape: + if (!d->lineEdit) + e->ignore(); + break; + #ifdef QT_KEYPAD_NAVIGATION +- case Qt::Key_Select: +- if (QApplicationPrivate::keypadNavigationEnabled() +- && (!hasEditFocus() || !d->lineEdit)) { +- showPopup(); +- return; +- } +- break; + case Qt::Key_Left: + case Qt::Key_Right: + if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus()) +diff --git a/qtbase/src/widgets/widgets/qdatetimeedit_p.h b/qtbase/src/widgets/widgets/qdatetimeedit_p.h +index d36b6f8f9a..e0df5b5158 100644 +--- a/qtbase/src/widgets/widgets/qdatetimeedit_p.h ++++ b/qtbase/src/widgets/widgets/qdatetimeedit_p.h +@@ -1,6 +1,6 @@ + /**************************************************************************** + ** +-** Copyright (C) 2018 The Qt Company Ltd. ++** Copyright (C) 2021 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the QtWidgets module of the Qt Toolkit. +diff --git a/qtbase/src/widgets/widgets/qgroupbox.cpp b/qtbase/src/widgets/widgets/qgroupbox.cpp +index 02a0bed325..3f3eccc370 100644 +--- a/qtbase/src/widgets/widgets/qgroupbox.cpp ++++ b/qtbase/src/widgets/widgets/qgroupbox.cpp +@@ -54,6 +54,8 @@ + #include "qaccessible.h" + #endif + #include ++#include ++#include + + #include "qdebug.h" + +@@ -360,7 +362,10 @@ bool QGroupBox::event(QEvent *e) + return true; + case QEvent::KeyPress: { + QKeyEvent *k = static_cast(e); +- if (!k->isAutoRepeat() && (k->key() == Qt::Key_Select || k->key() == Qt::Key_Space)) { ++ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() ++ ->themeHint(QPlatformTheme::ButtonPressKeys) ++ .value>(); ++ if (!k->isAutoRepeat() && buttonPressKeys.contains(static_cast(k->key()))) { + d->pressedControl = QStyle::SC_GroupBoxCheckBox; + update(style()->subControlRect(QStyle::CC_GroupBox, &box, QStyle::SC_GroupBoxCheckBox, this)); + return true; +@@ -369,7 +374,10 @@ bool QGroupBox::event(QEvent *e) + } + case QEvent::KeyRelease: { + QKeyEvent *k = static_cast(e); +- if (!k->isAutoRepeat() && (k->key() == Qt::Key_Select || k->key() == Qt::Key_Space)) { ++ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() ++ ->themeHint(QPlatformTheme::ButtonPressKeys) ++ .value>(); ++ if (!k->isAutoRepeat() && buttonPressKeys.contains(static_cast(k->key()))) { + bool toggle = (d->pressedControl == QStyle::SC_GroupBoxLabel + || d->pressedControl == QStyle::SC_GroupBoxCheckBox); + d->pressedControl = QStyle::SC_None; +diff --git a/qtbase/src/widgets/widgets/qlabel.cpp b/qtbase/src/widgets/widgets/qlabel.cpp +index 30ff80cbb0..cf2605c17c 100644 +--- a/qtbase/src/widgets/widgets/qlabel.cpp ++++ b/qtbase/src/widgets/widgets/qlabel.cpp +@@ -421,9 +421,6 @@ void QLabel::setPixmap(const QPixmap &pixmap) + d->pixmap = new QPixmap(pixmap); + } + +- if (d->pixmap->depth() == 1 && !d->pixmap->mask()) +- d->pixmap->setMask(*((QBitmap *)d->pixmap)); +- + d->updateLabel(); + } + +diff --git a/qtbase/src/widgets/widgets/qtoolbararealayout.cpp b/qtbase/src/widgets/widgets/qtoolbararealayout.cpp +index 493c094cc1..d5f4b59017 100644 +--- a/qtbase/src/widgets/widgets/qtoolbararealayout.cpp ++++ b/qtbase/src/widgets/widgets/qtoolbararealayout.cpp +@@ -1367,7 +1367,7 @@ bool QToolBarAreaLayout::restoreState(QDataStream &stream, const QListsetOrientation(floating ? ((shown & 2) ? Qt::Vertical : Qt::Horizontal) : dock.o); + toolBar->setVisible(shown & 1); +- toolBar->d_func()->setWindowState(floating, true, rect); ++ toolBar->d_func()->setWindowState(floating, false, rect); + + item.preferredSize = item.size; + line.toolBarItems.append(item); +diff --git a/qtbase/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp b/qtbase/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp +index 212c0a2e13..3c77b1ba0b 100644 +--- a/qtbase/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp ++++ b/qtbase/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp +@@ -126,8 +126,7 @@ public: + + void tst_QtConcurrentIterateKernel::instantiate() + { +- auto future = startThreadEngine(new PrintFor(0, 40)).startAsynchronously(); +- future.waitForFinished(); ++ startThreadEngine(new PrintFor(0, 40)).startBlocking(); + QCOMPARE(iterations.loadRelaxed(), 40); + } + +@@ -166,10 +165,8 @@ void tst_QtConcurrentIterateKernel::stresstest() + const int times = 50; + for (int i = 0; i < times; ++i) { + counter.storeRelaxed(0); +- // ThreadEngine will delete f when it finishes +- auto f = new CountFor(0, iterations); +- auto future = f->startAsynchronously(); +- future.waitForFinished(); ++ CountFor f(0, iterations); ++ f.startBlocking(); + QCOMPARE(counter.loadRelaxed(), iterations); + } + } +@@ -177,11 +174,8 @@ void tst_QtConcurrentIterateKernel::stresstest() + void tst_QtConcurrentIterateKernel::noIterations() + { + const int times = 20000; +- for (int i = 0; i < times; ++i) { +- auto future = startThreadEngine(new IterateKernel(0, 0)) +- .startAsynchronously(); +- future.waitForFinished(); +- } ++ for (int i = 0; i < times; ++i) ++ startThreadEngine(new IterateKernel(0, 0)).startBlocking(); + } + + QMutex threadsMutex; +@@ -236,10 +230,8 @@ void tst_QtConcurrentIterateKernel::throttling() + + threads.clear(); + +- // ThreadEngine will delete f when it finishes +- auto f = new ThrottleFor(0, totalIterations); +- auto future = f->startAsynchronously(); +- future.waitForFinished(); ++ ThrottleFor f(0, totalIterations); ++ f.startBlocking(); + + QCOMPARE(iterations.loadRelaxed(), totalIterations); + +diff --git a/qtbase/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp b/qtbase/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp +index ac7be7acdd..81bc64c8d9 100644 +--- a/qtbase/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp ++++ b/qtbase/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp +@@ -65,9 +65,16 @@ public: + + void tst_QtConcurrentThreadEngine::runDirectly() + { +- PrintUser *engine = new PrintUser(); +- QFuture f = engine->startAsynchronously(); +- f.waitForFinished(); ++ { ++ PrintUser engine; ++ engine.startSingleThreaded(); ++ engine.startBlocking(); ++ } ++ { ++ PrintUser *engine = new PrintUser(); ++ QFuture f = engine->startAsynchronously(); ++ f.waitForFinished(); ++ } + } + + class StringResultUser : public ThreadEngine +@@ -99,10 +106,8 @@ public: + + void tst_QtConcurrentThreadEngine::result() + { +- // ThreadEngine will delete 'engine' when it finishes +- auto engine = new StringResultUser(); +- auto future = engine->startAsynchronously(); +- QCOMPARE(future.result(), QString("Foo")); ++ StringResultUser engine; ++ QCOMPARE(*engine.startBlocking(), QString("Foo")); + } + + class VoidResultUser : public ThreadEngine +@@ -128,9 +133,17 @@ public: + + void tst_QtConcurrentThreadEngine::runThroughStarter() + { +- ThreadEngineStarter starter = startThreadEngine(new StringResultUser()); +- QFuture f = starter.startAsynchronously(); +- QCOMPARE(f.result(), QString("Foo")); ++ { ++ ThreadEngineStarter starter = startThreadEngine(new StringResultUser()); ++ QFuture f = starter.startAsynchronously(); ++ QCOMPARE(f.result(), QString("Foo")); ++ } ++ ++ { ++ ThreadEngineStarter starter = startThreadEngine(new StringResultUser()); ++ QString str = starter.startBlocking(); ++ QCOMPARE(str, QString("Foo")); ++ } + } + + class CancelUser : public ThreadEngine +@@ -213,6 +226,12 @@ void tst_QtConcurrentThreadEngine::throttle() + f.waitForFinished(); + QCOMPARE(count.loadRelaxed(), 0); + } ++ ++ for (int i = 0; i < repeats; ++i) { ++ ThrottleAlwaysUser t; ++ t.startBlocking(); ++ QCOMPARE(count.loadRelaxed(), 0); ++ } + } + + QSet threads; +@@ -249,17 +268,35 @@ void tst_QtConcurrentThreadEngine::threadCount() + { + const int repeats = 10; + for (int i = 0; i < repeats; ++i) { ++ ThreadCountUser t; ++ t.startBlocking(); ++ int count = threads.count(); ++ int count_expected = QThreadPool::globalInstance()->maxThreadCount() + 1; // +1 for the main thread. ++ if (count != count_expected) ++ QEXPECT_FAIL("", "QTBUG-23333", Abort); ++ QCOMPARE(count, count_expected); ++ + (new ThreadCountUser())->startAsynchronously().waitForFinished(); +- const auto count = threads.count(); +- const auto maxThreadCount = QThreadPool::globalInstance()->maxThreadCount(); +- QVERIFY(count <= maxThreadCount); +- QVERIFY(!threads.contains(QThread::currentThread())); ++ count = threads.count(); ++ count_expected = QThreadPool::globalInstance()->maxThreadCount(); ++ if (count != count_expected) ++ QEXPECT_FAIL("", "QTBUG-23333", Abort); ++ QCOMPARE(count, count_expected); + } + + // Set the finish flag immediately, this should give us one thread only. + for (int i = 0; i < repeats; ++i) { ++ ThreadCountUser t(true /*finishImmediately*/); ++ t.startBlocking(); ++ int count = threads.count(); ++ if (count != 1) ++ QEXPECT_FAIL("", "QTBUG-23333", Abort); ++ QCOMPARE(count, 1); ++ + (new ThreadCountUser(true /*finishImmediately*/))->startAsynchronously().waitForFinished(); +- const auto count = threads.count(); ++ count = threads.count(); ++ if (count != 1) ++ QEXPECT_FAIL("", "QTBUG-23333", Abort); + QCOMPARE(count, 1); + QVERIFY(!threads.contains(QThread::currentThread())); + } +@@ -400,6 +437,7 @@ public: + + void tst_QtConcurrentThreadEngine::exceptions() + { ++ // Asynchronous mode: + { + bool caught = false; + try { +@@ -412,6 +450,32 @@ void tst_QtConcurrentThreadEngine::exceptions() + QVERIFY2(caught, "did not get exception"); + } + ++ // Blocking mode: ++ // test throwing the exception from a worker thread. ++ { ++ bool caught = false; ++ try { ++ QtConcurrentExceptionThrower e(QThread::currentThread()); ++ e.startBlocking(); ++ } catch (const QException &) { ++ caught = true; ++ } ++ QVERIFY2(caught, "did not get exception"); ++ } ++ ++ // test throwing the exception from the main thread (different code path) ++ { ++ bool caught = false; ++ try { ++ QtConcurrentExceptionThrower e(0); ++ e.startBlocking(); ++ } catch (const QException &) { ++ caught = true; ++ } ++ QVERIFY2(caught, "did not get exception"); ++ } ++ ++ // Asynchronous mode: + { + bool caught = false; + try { +@@ -423,6 +487,31 @@ void tst_QtConcurrentThreadEngine::exceptions() + } + QVERIFY2(caught, "did not get exception"); + } ++ ++ // Blocking mode: ++ // test throwing the exception from a worker thread. ++ { ++ bool caught = false; ++ try { ++ UnrelatedExceptionThrower e(QThread::currentThread()); ++ e.startBlocking(); ++ } catch (const QUnhandledException &) { ++ caught = true; ++ } ++ QVERIFY2(caught, "did not get exception"); ++ } ++ ++ // test throwing the exception from the main thread (different code path) ++ { ++ bool caught = false; ++ try { ++ UnrelatedExceptionThrower e(0); ++ e.startBlocking(); ++ } catch (const QUnhandledException &) { ++ caught = true; ++ } ++ QVERIFY2(caught, "did not get exception"); ++ } + } + + #endif +diff --git a/qtbase/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp b/qtbase/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp +index 4968742110..f4c3fb711d 100644 +--- a/qtbase/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp ++++ b/qtbase/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp +@@ -42,6 +42,7 @@ private slots: + void writeBlock_data(); + void writeBlock(); + void seek(); ++ void invalidSeeks(); + void seekTest_data(); + void seekTest(); + void read_rawdata(); +@@ -286,6 +287,29 @@ void tst_QBuffer::seek() + QCOMPARE(buffer.size(), pos); + } + ++void tst_QBuffer::invalidSeeks() ++{ ++ if constexpr (sizeof(qsizetype) == sizeof(qint64)) { ++ // sizeof(qsizetype) == sizeof(qint64), so +1 would overflow ++ QSKIP("This is a 32-bit-only test."); ++ } else { ++ QBuffer buffer; ++ buffer.open(QIODevice::WriteOnly); ++ QCOMPARE(buffer.buffer().size(), qsizetype(0)); ++ QCOMPARE(buffer.pos(), qint64(0)); ++ constexpr qint64 MaxQByteArrayCapacity = (std::numeric_limits::max)(); ++ // this should fail fast, not after trying to allocate nearly 2 GiB of data, ++ // potentially crashing in the process: ++ QVERIFY(!buffer.seek(2 * MaxQByteArrayCapacity - 1)); ++ QCOMPARE(buffer.buffer().size(), qsizetype(0)); ++ QCOMPARE(buffer.pos(), qint64(0)); ++ // ditto: ++ QVERIFY(!buffer.seek(MaxQByteArrayCapacity + 1)); ++ QCOMPARE(buffer.buffer().size(), qsizetype(0)); ++ QCOMPARE(buffer.pos(), qint64(0)); ++ } ++} ++ + void tst_QBuffer::seekTest_data() + { + writeBlock_data(); +diff --git a/qtbase/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp b/qtbase/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp +index da5327594c..4a04e0f7c6 100644 +--- a/qtbase/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp ++++ b/qtbase/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp +@@ -561,7 +561,8 @@ protected: + qint64 readData(char *data, qint64 maxSize) override + { + maxSize = qMin(maxSize, qint64(buf->size() - offset)); +- memcpy(data, buf->constData() + offset, maxSize); ++ if (maxSize > 0) ++ memcpy(data, buf->constData() + offset, maxSize); + offset += maxSize; + return maxSize; + } +@@ -604,13 +605,15 @@ protected: + qint64 readData(char *data, qint64 maxSize) override + { + maxSize = qMin(maxSize, qint64(buf.size() - pos())); +- memcpy(data, buf.constData() + pos(), maxSize); ++ if (maxSize > 0) ++ memcpy(data, buf.constData() + pos(), maxSize); + return maxSize; + } + qint64 writeData(const char *data, qint64 maxSize) override + { + maxSize = qMin(maxSize, qint64(buf.size() - pos())); +- memcpy(buf.data() + pos(), data, maxSize); ++ if (maxSize > 0) ++ memcpy(buf.data() + pos(), data, maxSize); + return maxSize; + } + +diff --git a/qtbase/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/qtbase/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +index db60bead64..f345a44414 100644 +--- a/qtbase/tests/auto/corelib/io/qprocess/tst_qprocess.cpp ++++ b/qtbase/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +@@ -1,7 +1,8 @@ + /**************************************************************************** + ** + ** Copyright (C) 2021 The Qt Company Ltd. +-** Copyright (C) 2020 Intel Corporation. ++** Copyright (C) 2020 The Qt Company Ltd. ++** Copyright (C) 2022 Intel Corporation. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the test suite of the Qt Toolkit. +@@ -150,6 +151,8 @@ private slots: + void startStopStartStopBuffers(); + void processEventsInAReadyReadSlot_data(); + void processEventsInAReadyReadSlot(); ++ void startFromCurrentWorkingDir_data(); ++ void startFromCurrentWorkingDir(); + + // keep these at the end, since they use lots of processes and sometimes + // caused obscure failures to occur in tests that followed them (esp. on the Mac) +@@ -2731,5 +2734,94 @@ void tst_QProcess::finishProcessBeforeReadingDone_deprecated() + + #endif + ++enum class ChdirMode { ++ None = 0, ++ InParent, ++ InChild ++}; ++Q_DECLARE_METATYPE(ChdirMode) ++ ++void tst_QProcess::startFromCurrentWorkingDir_data() ++{ ++ qRegisterMetaType(); ++ QTest::addColumn("programPrefix"); ++ QTest::addColumn("chdirMode"); ++ QTest::addColumn("success"); ++ ++ constexpr bool IsWindows = true ++#ifdef Q_OS_UNIX ++ && false ++#endif ++ ; ++ ++ // baseline: trying to execute the directory, this can't possibly succeed! ++ QTest::newRow("plain-same-cwd") << QString() << ChdirMode::None << false; ++ ++ // cross-platform behavior: neither OS searches the setWorkingDirectory() ++ // dir without "./" ++ QTest::newRow("plain-child-chdir") << QString() << ChdirMode::InChild << false; ++ ++ // cross-platform behavior: both OSes search the parent's CWD with "./" ++ QTest::newRow("prefixed-parent-chdir") << "./" << ChdirMode::InParent << true; ++ ++ // opposite behaviors: Windows searches the parent's CWD and Unix searches ++ // the child's with "./" ++ QTest::newRow("prefixed-child-chdir") << "./" << ChdirMode::InChild << !IsWindows; ++ ++ // Windows searches the parent's CWD without "./" ++ QTest::newRow("plain-parent-chdir") << QString() << ChdirMode::InParent << IsWindows; ++} ++ ++void tst_QProcess::startFromCurrentWorkingDir() ++{ ++ QFETCH(QString, programPrefix); ++ QFETCH(ChdirMode, chdirMode); ++ QFETCH(bool, success); ++ ++ QProcess process; ++ qRegisterMetaType(); ++ QSignalSpy errorSpy(&process, &QProcess::errorOccurred); ++ QVERIFY(errorSpy.isValid()); ++ ++ // both the dir name and the executable name ++ const QString target = QStringLiteral("testProcessNormal"); ++ process.setProgram(programPrefix + target); ++ ++#ifdef Q_OS_UNIX ++ // Reset PATH, to be sure it doesn't contain . or the empty path. ++ // We can't do this on Windows because DLLs are searched in PATH ++ // and Windows always searches "." anyway. ++ auto restoreEnv = qScopeGuard([old = qgetenv("PATH")] { ++ qputenv("PATH", old); ++ }); ++ qputenv("PATH", "/"); ++#endif ++ ++ switch (chdirMode) { ++ case ChdirMode::InParent: { ++ auto restoreCwd = qScopeGuard([old = QDir::currentPath()] { ++ QDir::setCurrent(old); ++ }); ++ QVERIFY(QDir::setCurrent(target)); ++ process.start(); ++ break; ++ } ++ case ChdirMode::InChild: ++ process.setWorkingDirectory(target); ++ Q_FALLTHROUGH(); ++ case ChdirMode::None: ++ process.start(); ++ break; ++ } ++ ++ QCOMPARE(process.waitForStarted(), success); ++ QCOMPARE(errorSpy.count(), int(!success)); ++ if (success) { ++ QVERIFY(process.waitForFinished()); ++ } else { ++ QCOMPARE(process.error(), QProcess::FailedToStart); ++ } ++} ++ + QTEST_MAIN(tst_QProcess) + #include "tst_qprocess.moc" +diff --git a/qtbase/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp b/qtbase/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp +index e1ea7a4552..90972caa57 100644 +--- a/qtbase/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp ++++ b/qtbase/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp +@@ -117,6 +117,7 @@ private Q_SLOTS: + void shouldPropagateDropAfterLastRow_data(); + void shouldPropagateDropAfterLastRow(); + void qtbug91788(); ++ void qtbug91878(); + + private: + QStandardItemModel mod; +@@ -843,6 +844,22 @@ void tst_QConcatenateTablesProxyModel::qtbug91788() + QCOMPARE(proxyConcat.columnCount(), 0); + } + ++void tst_QConcatenateTablesProxyModel::qtbug91878() ++{ ++ QStandardItemModel m; ++ m.setRowCount(4); ++ m.setColumnCount(4); ++ ++ QConcatenateTablesProxyModel pm; ++ QSortFilterProxyModel proxyFilter; ++ proxyFilter.setSourceModel(&pm); ++ proxyFilter.setFilterFixedString("something"); ++ pm.addSourceModel(&m); // This should not assert ++ ++ QCOMPARE(pm.columnCount(), 4); ++ QCOMPARE(pm.rowCount(), 4); ++} ++ + QTEST_GUILESS_MAIN(tst_QConcatenateTablesProxyModel) + + #include "tst_qconcatenatetablesproxymodel.moc" +diff --git a/qtbase/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/qtbase/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +index 9bd66c0835..ed4a0bae5d 100644 +--- a/qtbase/tests/auto/corelib/kernel/qobject/tst_qobject.cpp ++++ b/qtbase/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +@@ -158,6 +158,7 @@ private slots: + void nullReceiver(); + void functorReferencesConnection(); + void disconnectDisconnects(); ++ void declarativeData(); + }; + + struct QObjectCreatedOnShutdown +@@ -7679,5 +7680,81 @@ void tst_QObject::disconnectDisconnects() + Q_STATIC_ASSERT(QtPrivate::HasQ_OBJECT_Macro::Value); + Q_STATIC_ASSERT(!QtPrivate::HasQ_OBJECT_Macro::Value); + ++#ifdef QT_BUILD_INTERNAL ++/* ++ Since QObjectPrivate stores the declarativeData pointer in a union with the pointer ++ to the currently destroyed child, calls to the QtDeclarative handlers need to be ++ correctly guarded. QTBUG-105286 ++*/ ++namespace QtDeclarative { ++static QAbstractDeclarativeData *theData; ++ ++static void destroyed(QAbstractDeclarativeData *data, QObject *) ++{ ++ QCOMPARE(data, theData); ++} ++static void signalEmitted(QAbstractDeclarativeData *data, QObject *, int, void **) ++{ ++ QCOMPARE(data, theData); ++} ++// we can't use QCOMPARE in the next two functions, as they don't return void ++static int receivers(QAbstractDeclarativeData *data, const QObject *, int) ++{ ++ QTest::qCompare(data, theData, "data", "theData", __FILE__, __LINE__); ++ return 0; ++} ++static bool isSignalConnected(QAbstractDeclarativeData *data, const QObject *, int) ++{ ++ QTest::qCompare(data, theData, "data", "theData", __FILE__, __LINE__); ++ return true; ++} ++ ++class Object : public QObject ++{ ++ Q_OBJECT ++public: ++ using QObject::QObject; ++ ~Object() ++ { ++ if (Object *p = static_cast(parent())) ++ p->emitSignal(); ++ } ++ ++ void emitSignal() ++ { ++ emit theSignal(); ++ } ++ ++signals: ++ void theSignal(); ++}; ++ ++} ++#endif ++ ++void tst_QObject::declarativeData() ++{ ++#ifdef QT_BUILD_INTERNAL ++ QScopedValueRollback destroyed(QAbstractDeclarativeData::destroyed, ++ QtDeclarative::destroyed); ++ QScopedValueRollback signalEmitted(QAbstractDeclarativeData::signalEmitted, ++ QtDeclarative::signalEmitted); ++ QScopedValueRollback receivers(QAbstractDeclarativeData::receivers, ++ QtDeclarative::receivers); ++ QScopedValueRollback isSignalConnected(QAbstractDeclarativeData::isSignalConnected, ++ QtDeclarative::isSignalConnected); ++ ++ QtDeclarative::Object p; ++ QObjectPrivate *priv = QObjectPrivate::get(&p); ++ priv->declarativeData = QtDeclarative::theData = new QAbstractDeclarativeData; ++ ++ connect(&p, &QtDeclarative::Object::theSignal, &p, []{ ++ }); ++ ++ QtDeclarative::Object *child = new QtDeclarative::Object; ++ child->setParent(&p); ++#endif ++} ++ + QTEST_MAIN(tst_QObject) + #include "tst_qobject.moc" +diff --git a/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp b/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp +index 0ea422ecbc..1a3256534b 100644 +--- a/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp ++++ b/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp +@@ -70,15 +70,15 @@ static inline QString testSuiteWarning() + + QString result; + QTextStream str(&result); +- str << "\nCannot find the shared-mime-info test suite\nstarting from: " ++ str << "\nCannot find the shared-mime-info test suite\nin the parent of: " + << QDir::toNativeSeparators(QDir::currentPath()) << "\n" + "cd " << QDir::toNativeSeparators(QStringLiteral("tests/auto/corelib/mimetypes/qmimedatabase")) << "\n" +- "wget http://cgit.freedesktop.org/xdg/shared-mime-info/snapshot/Release-1-10.zip\n" +- "unzip Release-1-10.zip\n"; ++ "wget https://gitlab.freedesktop.org/xdg/shared-mime-info/-/archive/2.1/shared-mime-info-2.1.zip\n" ++ "unzip shared-mime-info-2.1.zip\n"; + #ifdef Q_OS_WIN +- str << "mkdir testfiles\nxcopy /s Release-1-10 s-m-i\n"; ++ str << "mkdir testfiles\nxcopy /s shared-mime-info-2.1 s-m-i\n"; + #else +- str << "ln -s Release-1-10 s-m-i\n"; ++ str << "ln -s shared-mime-info-2.1 s-m-i\n"; + #endif + return result; + } +@@ -154,7 +154,7 @@ void tst_QMimeDatabase::initTestCase() + QVERIFY2(copyResourceFile(xmlFileName, xmlTargetFileName, &errorMessage), qPrintable(errorMessage)); + #endif + +- m_testSuite = QFINDTESTDATA("s-m-i/tests"); ++ m_testSuite = QFINDTESTDATA("s-m-i/tests/mime-detection"); + if (m_testSuite.isEmpty()) + qWarning("%s", qPrintable(testSuiteWarning())); + +@@ -611,7 +611,7 @@ void tst_QMimeDatabase::allMimeTypes() + QVERIFY(!lst.isEmpty()); + + // Hardcoding this is the only way to check both providers find the same number of mimetypes. +- QCOMPARE(lst.count(), 779); ++ QCOMPARE(lst.count(), 811); + + foreach (const QMimeType &mime, lst) { + const QString name = mime.name(); +@@ -631,10 +631,9 @@ void tst_QMimeDatabase::suffixes_data() + + QTest::newRow("mimetype with a single pattern") << "application/pdf" << "*.pdf" << "pdf"; + QTest::newRow("mimetype with multiple patterns") << "application/x-kpresenter" << "*.kpr;*.kpt" << "kpr"; +- QTest::newRow("jpeg") << "image/jpeg" << "*.jpe;*.jpg;*.jpeg" << "jpeg"; +- //if (KMimeType::sharedMimeInfoVersion() > KDE_MAKE_VERSION(0, 60, 0)) { +- QTest::newRow("mimetype with many patterns") << "application/vnd.wordperfect" << "*.wp;*.wp4;*.wp5;*.wp6;*.wpd;*.wpp" << "wp"; +- //} ++ // The preferred suffix for image/jpeg is *.jpg, as per https://bugs.kde.org/show_bug.cgi?id=176737 ++ QTest::newRow("jpeg") << "image/jpeg" << "*.jpe;*.jpg;*.jpeg" << "jpg"; ++ QTest::newRow("mimetype with many patterns") << "application/vnd.wordperfect" << "*.wp;*.wp4;*.wp5;*.wp6;*.wpd;*.wpp" << "wp"; + QTest::newRow("oasis text mimetype") << "application/vnd.oasis.opendocument.text" << "*.odt" << "odt"; + QTest::newRow("oasis presentation mimetype") << "application/vnd.oasis.opendocument.presentation" << "*.odp" << "odp"; + QTest::newRow("mimetype with multiple patterns") << "text/plain" << "*.asc;*.txt;*,v" << "txt"; +diff --git a/qtbase/tests/auto/corelib/serialization/json/tst_qtjson.cpp b/qtbase/tests/auto/corelib/serialization/json/tst_qtjson.cpp +index 3e58dd03cc..c8f82ef5d5 100644 +--- a/qtbase/tests/auto/corelib/serialization/json/tst_qtjson.cpp ++++ b/qtbase/tests/auto/corelib/serialization/json/tst_qtjson.cpp +@@ -176,6 +176,8 @@ private Q_SLOTS: + void fromToVariantConversions_data(); + void fromToVariantConversions(); + ++ void noLeakOnNameClash(); ++ + private: + QString testDataDir; + }; +@@ -3685,5 +3687,23 @@ void tst_QtJson::fromToVariantConversions() + } + } + ++void tst_QtJson::noLeakOnNameClash() ++{ ++ QJsonDocument doc = QJsonDocument::fromJson("{\"\":{\"\":0},\"\":0}"); ++ QVERIFY(!doc.isNull()); ++ const QJsonObject obj = doc.object(); ++ ++ // Removed the duplicate key. ++ QCOMPARE(obj.length(), 1); ++ ++ // Retained the last of the duplicates. ++ const QJsonValue val = obj.begin().value(); ++ QVERIFY(val.isDouble()); ++ QCOMPARE(val.toDouble(), 0.0); ++ ++ // It should not leak. ++ // In particular it should not forget to deref the container for the inner object. ++} ++ + QTEST_MAIN(tst_QtJson) + #include "tst_qtjson.moc" +diff --git a/qtbase/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp b/qtbase/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp +index a59b58d57f..241c3e84ac 100644 +--- a/qtbase/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp ++++ b/qtbase/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp +@@ -63,6 +63,7 @@ private slots: + void isValidId_data(); + void isValidId(); + void malformed(); ++ void serialize(); + // Backend tests + void utcTest(); + void icuTest(); +@@ -947,6 +948,33 @@ void tst_QTimeZone::malformed() + barf.offsetFromUtc(now); + } + ++void tst_QTimeZone::serialize() ++{ ++ int parts = 0; ++#ifndef QT_NO_DEBUG_STREAM ++ qDebug() << QTimeZone(); // to verify no crash ++ parts++; ++#endif ++#ifndef QT_NO_DATASTREAM ++ QByteArray blob; ++ { ++ QDataStream stream(&blob, QIODevice::WriteOnly); ++ stream << QTimeZone("Europe/Oslo") << QTimeZone(420) << QTimeZone() << qint64(-1); ++ } ++ QDataStream stream(&blob, QIODevice::ReadOnly); ++ QTimeZone invalid, offset, oslo; ++ qint64 minusone; ++ stream >> oslo >> offset >> invalid >> minusone; ++ QCOMPARE(oslo, QTimeZone("Europe/Oslo")); ++ QCOMPARE(offset, QTimeZone(420)); ++ QVERIFY(!invalid.isValid()); ++ QCOMPARE(minusone, qint64(-1)); ++ parts++; ++#endif ++ if (!parts) ++ QSKIP("No serialization enabled"); ++} ++ + void tst_QTimeZone::utcTest() + { + #ifdef QT_BUILD_INTERNAL +diff --git a/qtbase/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp b/qtbase/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp +index 05480c6dd2..70f4c75756 100644 +--- a/qtbase/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp ++++ b/qtbase/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp +@@ -324,6 +324,13 @@ void tst_QDBusInterface::notValid() + + QVERIFY(!interface.isValid()); + QVERIFY(!QMetaObject::invokeMethod(&interface, "ListNames", Qt::DirectConnection)); ++ ++ // With a connection, but empty/null service and path specified ++ QDBusConnection con = QDBusConnection::sessionBus(); ++ QVERIFY(con.isConnected()); ++ QDBusInterface iface({}, {}, {}, con); ++ QVERIFY(!iface.isValid()); ++ QVERIFY(!QMetaObject::invokeMethod(&interface, "ListNames", Qt::DirectConnection)); + } + + void tst_QDBusInterface::notValidDerived() +diff --git a/qtbase/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp b/qtbase/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp +index 874468c954..04ceb4ab65 100644 +--- a/qtbase/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp ++++ b/qtbase/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp +@@ -507,6 +507,10 @@ void tst_QKeySequence::toStringFromKeycode_data() + QTest::newRow("Ctrl+Alt+Num+Del") << QKeySequence(Qt::ControlModifier | Qt::AltModifier | Qt::KeypadModifier | Qt::Key_Delete) << "Ctrl+Alt+Num+Del"; + QTest::newRow("Ctrl+Ins") << QKeySequence(Qt::ControlModifier | Qt::Key_Insert) << "Ctrl+Ins"; + QTest::newRow("Ctrl+Num+Ins(1)") << QKeySequence(Qt::Key_Insert | Qt::KeypadModifier | Qt::ControlModifier) << "Ctrl+Num+Ins"; ++ QTest::newRow("Ctrl") << QKeySequence(Qt::Key_Control) << "Control"; ++ QTest::newRow("Alt") << QKeySequence(Qt::Key_Alt) << "Alt"; ++ QTest::newRow("Shift") << QKeySequence(Qt::Key_Shift) << "Shift"; ++ QTest::newRow("Meta") << QKeySequence(Qt::Key_Meta) << "Meta"; + } + + void tst_QKeySequence::toStringFromKeycode() +diff --git a/qtbase/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp b/qtbase/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp +index 15e0ecadaa..b4eca74283 100644 +--- a/qtbase/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp ++++ b/qtbase/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp +@@ -81,6 +81,8 @@ private slots: + void registerOpenTypePreferredNamesSystem(); + void registerOpenTypePreferredNamesApplication(); + ++ void stretchRespected(); ++ + private: + QString m_ledFont; + QString m_testFont; +@@ -355,6 +357,28 @@ static QString testString() + return QStringLiteral("foo bar"); + } + ++void tst_QFontDatabase::stretchRespected() ++{ ++ int italicId = QFontDatabase::addApplicationFont(m_testFontItalic); ++ QVERIFY(italicId != -1); ++ ++ QVERIFY(!QFontDatabase::applicationFontFamilies(italicId).isEmpty()); ++ ++ QString italicFontName = QFontDatabase::applicationFontFamilies(italicId).first(); ++ ++ QFont italicFont = QFontDatabase().font(italicFontName, ++ QString::fromLatin1("Italic"), 14); ++ QVERIFY(italicFont.italic()); ++ ++ QFont italicStretchedFont = italicFont; ++ italicStretchedFont.setStretch( 400 ); ++ ++ QVERIFY(QFontMetricsF(italicFont).horizontalAdvance(QStringLiteral("foobar")) < ++ QFontMetricsF(italicStretchedFont).horizontalAdvance(QStringLiteral("foobar"))); ++ ++ QFontDatabase::removeApplicationFont(italicId); ++} ++ + void tst_QFontDatabase::condensedFontWidthNoFontMerging() + { + int regularFontId = QFontDatabase::addApplicationFont(m_testFont); +diff --git a/qtbase/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/qtbase/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +index 3d4a094c43..b423e11a99 100644 +--- a/qtbase/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp ++++ b/qtbase/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +@@ -281,6 +281,7 @@ private Q_SLOTS: + void ioGetFromFileSpecial(); + void ioGetFromFile_data(); + void ioGetFromFile(); ++ void ioGetFromFileUrl(); + void ioGetFromFtp_data(); + void ioGetFromFtp(); + void ioGetFromFtpWithReuse(); +@@ -3300,6 +3301,18 @@ void tst_QNetworkReply::ioGetFromFile() + QCOMPARE(reader.data, data); + } + ++void tst_QNetworkReply::ioGetFromFileUrl() ++{ ++ // This immediately fails on non-windows platforms: ++ QNetworkRequest request(QUrl("file://unc-server/some/path")); ++ QNetworkReplyPtr reply(manager.get(request)); ++ QSignalSpy finishedSpy(reply.get(), &QNetworkReply::finished); ++ // QTBUG-105618: This would, on non-Windows platforms, never happen because the signal ++ // was emitted before the constructor finished, leaving no chance at all to connect to the ++ // signal ++ QVERIFY(finishedSpy.wait()); ++} ++ + void tst_QNetworkReply::ioGetFromFtp_data() + { + QTest::addColumn("fileName"); +diff --git a/qtbase/tests/auto/network/ssl/qsslsocket/certs/fluke.cert b/qtbase/tests/auto/network/ssl/qsslsocket/certs/fluke.cert +index 069fa6b341..4cc4d9a5ea 100644 +--- a/qtbase/tests/auto/network/ssl/qsslsocket/certs/fluke.cert ++++ b/qtbase/tests/auto/network/ssl/qsslsocket/certs/fluke.cert +@@ -1,75 +1,34 @@ +-Certificate: +- Data: +- Version: 3 (0x2) +- Serial Number: 0 (0x0) +- Signature Algorithm: sha1WithRSAEncryption +- Issuer: C=NO, ST=Oslo, L=Nydalen, O=Nokia Corporation and/or its subsidiary(-ies), OU=Development, CN=fluke.troll.no/emailAddress=ahanssen@trolltech.com +- Validity +- Not Before: Dec 4 01:10:32 2007 GMT +- Not After : Apr 21 01:10:32 2035 GMT +- Subject: C=NO, ST=Oslo, O=Nokia Corporation and/or its subsidiary(-ies), OU=Development, CN=fluke.troll.no +- Subject Public Key Info: +- Public Key Algorithm: rsaEncryption +- RSA Public Key: (1024 bit) +- Modulus (1024 bit): +- 00:a7:c8:a0:4a:c4:19:05:1b:66:ba:32:e2:d2:f1: +- 1c:6f:17:82:e4:39:2e:01:51:90:db:04:34:32:11: +- 21:c2:0d:6f:59:d8:53:90:54:3f:83:8f:a9:d3:b3: +- d5:ee:1a:9b:80:ae:c3:25:c9:5e:a5:af:4b:60:05: +- aa:a0:d1:91:01:1f:ca:04:83:e3:58:1c:99:32:45: +- 84:70:72:58:03:98:4a:63:8b:41:f5:08:49:d2:91: +- 02:60:6b:e4:64:fe:dd:a0:aa:74:08:e9:34:4c:91: +- 5f:12:3d:37:4d:54:2c:ad:7f:5b:98:60:36:02:8c: +- 3b:f6:45:f3:27:6a:9b:94:9d +- Exponent: 65537 (0x10001) +- X509v3 extensions: +- X509v3 Basic Constraints: +- CA:FALSE +- Netscape Comment: +- OpenSSL Generated Certificate +- X509v3 Subject Key Identifier: +- 21:85:04:3D:23:01:66:E5:F7:9F:1A:84:24:8A:AF:0A:79:F4:E5:AC +- X509v3 Authority Key Identifier: +- DirName:/C=NO/ST=Oslo/L=Nydalen/O=Nokia Corporation and/or its subsidiary(-ies)/OU=Development/CN=fluke.troll.no/emailAddress=ahanssen@trolltech.com +- serial:8E:A8:B4:E8:91:B7:54:2E +- +- Signature Algorithm: sha1WithRSAEncryption +- 6d:57:5f:d1:05:43:f0:62:05:ec:2a:71:a5:dc:19:08:f2:c4: +- a6:bd:bb:25:d9:ca:89:01:0e:e4:cf:1f:c1:8c:c8:24:18:35: +- 53:59:7b:c0:43:b4:32:e6:98:b2:a6:ef:15:05:0b:48:5f:e1: +- a0:0c:97:a9:a1:77:d8:35:18:30:bc:a9:8f:d3:b7:54:c7:f1: +- a9:9e:5d:e6:19:bf:f6:3c:5b:2b:d8:e4:3e:62:18:88:8b:d3: +- 24:e1:40:9b:0c:e6:29:16:62:ab:ea:05:24:70:36:aa:55:93: +- ef:02:81:1b:23:10:a2:04:eb:56:95:75:fc:f8:94:b1:5d:42: +- c5:3f:36:44:85:5d:3a:2e:90:46:8a:a2:b9:6f:87:ae:0c:15: +- 40:19:31:90:fc:3b:25:bb:ae:f1:66:13:0d:85:90:d9:49:34: +- 8f:f2:5d:f9:7a:db:4d:5d:27:f6:76:9d:35:8c:06:a6:4c:a3: +- b1:b2:b6:6f:1d:d7:a3:00:fd:72:eb:9e:ea:44:a1:af:21:34: +- 7d:c7:42:e2:49:91:19:8b:c0:ad:ba:82:80:a8:71:70:f4:35: +- 31:91:63:84:20:95:e9:60:af:64:8b:cc:ff:3d:8a:76:74:3d: +- c8:55:6d:e4:8e:c3:2b:1c:e8:42:18:ae:9f:e6:6b:9c:34:06: +- ec:6a:f2:c3 + -----BEGIN CERTIFICATE----- +-MIIEEzCCAvugAwIBAgIBADANBgkqhkiG9w0BAQUFADCBnDELMAkGA1UEBhMCTk8x +-DTALBgNVBAgTBE9zbG8xEDAOBgNVBAcTB055ZGFsZW4xFjAUBgNVBAoTDVRyb2xs +-dGVjaCBBU0ExFDASBgNVBAsTC0RldmVsb3BtZW50MRcwFQYDVQQDEw5mbHVrZS50 +-cm9sbC5ubzElMCMGCSqGSIb3DQEJARYWYWhhbnNzZW5AdHJvbGx0ZWNoLmNvbTAe +-Fw0wNzEyMDQwMTEwMzJaFw0zNTA0MjEwMTEwMzJaMGMxCzAJBgNVBAYTAk5PMQ0w +-CwYDVQQIEwRPc2xvMRYwFAYDVQQKEw1Ucm9sbHRlY2ggQVNBMRQwEgYDVQQLEwtE +-ZXZlbG9wbWVudDEXMBUGA1UEAxMOZmx1a2UudHJvbGwubm8wgZ8wDQYJKoZIhvcN +-AQEBBQADgY0AMIGJAoGBAKfIoErEGQUbZroy4tLxHG8XguQ5LgFRkNsENDIRIcIN +-b1nYU5BUP4OPqdOz1e4am4CuwyXJXqWvS2AFqqDRkQEfygSD41gcmTJFhHByWAOY +-SmOLQfUISdKRAmBr5GT+3aCqdAjpNEyRXxI9N01ULK1/W5hgNgKMO/ZF8ydqm5Sd +-AgMBAAGjggEaMIIBFjAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NM +-IEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUIYUEPSMBZuX3nxqEJIqv +-Cnn05awwgbsGA1UdIwSBszCBsKGBoqSBnzCBnDELMAkGA1UEBhMCTk8xDTALBgNV +-BAgTBE9zbG8xEDAOBgNVBAcTB055ZGFsZW4xFjAUBgNVBAoTDVRyb2xsdGVjaCBB +-U0ExFDASBgNVBAsTC0RldmVsb3BtZW50MRcwFQYDVQQDEw5mbHVrZS50cm9sbC5u +-bzElMCMGCSqGSIb3DQEJARYWYWhhbnNzZW5AdHJvbGx0ZWNoLmNvbYIJAI6otOiR +-t1QuMA0GCSqGSIb3DQEBBQUAA4IBAQBtV1/RBUPwYgXsKnGl3BkI8sSmvbsl2cqJ +-AQ7kzx/BjMgkGDVTWXvAQ7Qy5piypu8VBQtIX+GgDJepoXfYNRgwvKmP07dUx/Gp +-nl3mGb/2PFsr2OQ+YhiIi9Mk4UCbDOYpFmKr6gUkcDaqVZPvAoEbIxCiBOtWlXX8 +-+JSxXULFPzZEhV06LpBGiqK5b4euDBVAGTGQ/Dslu67xZhMNhZDZSTSP8l35ettN +-XSf2dp01jAamTKOxsrZvHdejAP1y657qRKGvITR9x0LiSZEZi8CtuoKAqHFw9DUx +-kWOEIJXpYK9ki8z/PYp2dD3IVW3kjsMrHOhCGK6f5mucNAbsavLD ++MIIF6zCCA9OgAwIBAgIUfo9amJtJGWqWE6f+SkAO85zkGr4wDQYJKoZIhvcNAQEL ++BQAwgYMxCzAJBgNVBAYTAk5PMQ0wCwYDVQQIDARPc2xvMQ0wCwYDVQQHDARPc2xv ++MRcwFQYDVQQKDA5UaGUgUXQgQ29tcGFueTEMMAoGA1UECwwDUiZEMRIwEAYDVQQD ++DAlIMiBUZXN0ZXIxGzAZBgkqhkiG9w0BCQEWDG1pbmltaUBxdC5pbzAgFw0yMDEw ++MjYxMjAxMzFaGA8yMTIwMTAwMjEyMDEzMVowgYMxCzAJBgNVBAYTAk5PMQ0wCwYD ++VQQIDARPc2xvMQ0wCwYDVQQHDARPc2xvMRcwFQYDVQQKDA5UaGUgUXQgQ29tcGFu ++eTEMMAoGA1UECwwDUiZEMRIwEAYDVQQDDAlIMiBUZXN0ZXIxGzAZBgkqhkiG9w0B ++CQEWDG1pbmltaUBxdC5pbzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB ++AOiUp5+E4blouKH7q+rVNR8NoYX2XkBW+q+rpy1zu5ssRSzbqxAjDx9dkht7Qlnf ++VlDT00JvpOWdeuPon5915edQRsY4Unl6mKH29ra3OtUa1/yCJXsGVJTKCj7k4Bxb ++5mZzb/fTlZntMLdTIBMfUbw62FKir1WjKIcJ9fCoG8JaGeKVO4Rh5p0ezd4UUUId ++r1BXl5Nqdqy2vTMsEDnjOsD3egkv8I2SKN4O6n/C3wWYpMOWYZkGoZiKz7rJs/i/ ++ez7bsV7JlwdzTlhpJzkcOSVFBP6JlEOxTNNxZ1wtKy7PtZGmsSSATq2e6+bw38Ae ++Op0XnzzqcGjtDDofBmT7OFzZWjS9VZS6+DOOe2QHWle1nCHcHyH4ku6IRlsr9xkR ++NAIlOfnvHHxqJUenoeaZ4oQDjCBKS1KXygJO/tL7BLTQVn/xK1EmPvKNnjzWk4tR ++PnibUhhs5635qpOU/YPqFBh1JjVruZbsWcDAhRcew0uxONXOa9E+4lttQ9ySYa1A ++LvWqJuAX7gu2BsBMLyqfm811YnA7CIFMyO+HlqmkLFfv5L/xIRAXR7l26YGO0VwX ++CGjMfz4NVPMMke4nB7qa9NkpXQBQKMms3Qzd5JW0Hy9Ruj5O8GPcFZmV0twjd1uJ ++PD/cAjkWLaXjdNsJ16QWc2nghQRS6HYqKRX6j+CXOxupAgMBAAGjUzBRMB0GA1Ud ++DgQWBBRSCOU58j9NJZkMamt623qyCrhN3TAfBgNVHSMEGDAWgBRSCOU58j9NJZkM ++amt623qyCrhN3TAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQCq ++q4jxsWeNDv5Nq14hJtF9HB+ZL64zcZtRjJP1YgNs0QppKICmjPOL2nIMGmI/jKrs ++0eGAL/9XXNVHPxm1OPOncvimMMmU6emZfpMdEtTfKP43+Pg9HgKRjLoQp406vGeQ ++8ki/mbBhrItVPgEm3tu2AFA02XTYi+YxCI9kRZLGkM3FbgtOuTLPl0Z9y+kiPc9F ++uCSC03anBEqv+vDSI8+wODymQ/IJ3Jyz1lxIRDfp4qAekmy0jU2c91VOHHEmOmqq ++kqygGFRdwbe99m9yP63r6q0b5K3X2UnJ6bns0hmTwThYwpVPXLU8jdaTddbMukN2 ++/Ef96Tsw8nWOEOPMySHOTIPgwyZRp26b0kA9EmhLwOP401SxXVQCmSRmtwNagmtg ++jJKmZoYBN+//D45ibK8z6Q0oOm9P+Whf/uUXehcRxBxyV3xz7k0wKGQbHj/ddwcy ++IUoIN4lrAlib+lK170kTKN352PDmrpo2gmIzPEsfurKAIMSelDl6H+kih16BtZ8y ++Nz6fh9Soqrg3OSAware8pxV7k51crBMoPLN78KoRV8MFCK4K7Fddq4rRISq6hiXq ++r1nsjoEPuKM9huprmZVZe9t5YcDa2I+wb3IiE3uwpZbAdaLDyQ5n6F/qpsiIkZXn ++gtcF7oqpG5oYrwCcZ53y/ezUgUg7PlSz2XwAGvQtgg== + -----END CERTIFICATE----- +diff --git a/qtbase/tests/auto/network/ssl/qsslsocket/certs/fluke.key b/qtbase/tests/auto/network/ssl/qsslsocket/certs/fluke.key +index 9d1664d609..337ce541a6 100644 +--- a/qtbase/tests/auto/network/ssl/qsslsocket/certs/fluke.key ++++ b/qtbase/tests/auto/network/ssl/qsslsocket/certs/fluke.key +@@ -1,15 +1,52 @@ +------BEGIN RSA PRIVATE KEY----- +-MIICXAIBAAKBgQCnyKBKxBkFG2a6MuLS8RxvF4LkOS4BUZDbBDQyESHCDW9Z2FOQ +-VD+Dj6nTs9XuGpuArsMlyV6lr0tgBaqg0ZEBH8oEg+NYHJkyRYRwclgDmEpji0H1 +-CEnSkQJga+Rk/t2gqnQI6TRMkV8SPTdNVCytf1uYYDYCjDv2RfMnapuUnQIDAQAB +-AoGANFzLkanTeSGNFM0uttBipFT9F4a00dqHz6JnO7zXAT26I5r8sU1pqQBb6uLz +-/+Qz5Zwk8RUAQcsMRgJetuPQUb0JZjF6Duv24hNazqXBCu7AZzUenjafwmKC/8ri +-KpX3fTwqzfzi//FKGgbXQ80yykSSliDL3kn/drATxsLCgQECQQDXhEFWLJ0vVZ1s +-1Ekf+3NITE+DR16X+LQ4W6vyEHAjTbaNWtcTKdAWLA2l6N4WAAPYSi6awm+zMxx4 +-VomVTsjdAkEAx0z+e7natLeFcrrq8pbU+wa6SAP1VfhQWKitxL1e7u/QO90NCpxE +-oQYKzMkmmpOOFjQwEMAy1dvFMbm4LHlewQJAC/ksDBaUcQHHqjktCtrUb8rVjAyW +-A8lscckeB2fEYyG5J6dJVaY4ClNOOs5yMDS2Afk1F6H/xKvtQ/5CzInA/QJATDub +-K+BPU8jO9q+gpuIi3VIZdupssVGmCgObVCHLakG4uO04y9IyPhV9lA9tALtoIf4c +-VIvv5fWGXBrZ48kZAQJBAJmVCdzQxd9LZI5vxijUCj5EI4e+x5DRqVUvyP8KCZrC +-AiNyoDP85T+hBZaSXK3aYGpVwelyj3bvo1GrTNwNWLw= +------END RSA PRIVATE KEY----- ++-----BEGIN PRIVATE KEY----- ++MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDolKefhOG5aLih +++6vq1TUfDaGF9l5AVvqvq6ctc7ubLEUs26sQIw8fXZIbe0JZ31ZQ09NCb6TlnXrj ++6J+fdeXnUEbGOFJ5epih9va2tzrVGtf8giV7BlSUygo+5OAcW+Zmc2/305WZ7TC3 ++UyATH1G8OthSoq9VoyiHCfXwqBvCWhnilTuEYeadHs3eFFFCHa9QV5eTanastr0z ++LBA54zrA93oJL/CNkijeDup/wt8FmKTDlmGZBqGYis+6ybP4v3s+27FeyZcHc05Y ++aSc5HDklRQT+iZRDsUzTcWdcLSsuz7WRprEkgE6tnuvm8N/AHjqdF5886nBo7Qw6 ++HwZk+zhc2Vo0vVWUuvgzjntkB1pXtZwh3B8h+JLuiEZbK/cZETQCJTn57xx8aiVH ++p6HmmeKEA4wgSktSl8oCTv7S+wS00FZ/8StRJj7yjZ481pOLUT54m1IYbOet+aqT ++lP2D6hQYdSY1a7mW7FnAwIUXHsNLsTjVzmvRPuJbbUPckmGtQC71qibgF+4LtgbA ++TC8qn5vNdWJwOwiBTMjvh5appCxX7+S/8SEQF0e5dumBjtFcFwhozH8+DVTzDJHu ++Jwe6mvTZKV0AUCjJrN0M3eSVtB8vUbo+TvBj3BWZldLcI3dbiTw/3AI5Fi2l43Tb ++CdekFnNp4IUEUuh2KikV+o/glzsbqQIDAQABAoICAFw1q6tr5I48vY7DF+rXsuLn ++5ZUWE1IQ6fzB4lr72nJv/9EEGnMgYzt9PpMUsD6vdCpBgS2C0+6RHArFzJtNA+RM ++iHLIG7K7702veyr/xBx/MwiSlMeMv/XpkFxVI6E6skMGG2s3AMXxKvJTy5CpRx+I ++eQFyLG+Ya1X2lgJes/q+/CpAHkOjCOpcLySQC5NZ74q734V7nSdmn+Zs3tYEh+O/ ++eiuwTP/j5b38Te5vVTqDxTciJPmljmXLCwa0N100lWlbcpvw8qbqiTI2Jm3XCbUE ++AzHjW9vmrF3cRS1fXxKFGShw3SRqlkbxjfeWoi8qDPUBS4m8LOr8qG9Wo5Nfon0z ++zLP4bci3zHDvVcaaZrrsUBs/yZbg+Dgka1DmX7ekmeccr2yTdKDFgPupYUyxVbTl ++a9ZLJysjFD7rgBv1ZclHonLp6Vbm+ZoTqvteo4ikAy6L9RtBWJ23XEK34PkP/+c5 ++2vWZaOrnjSeBHbFce8cdJSxqWpP+eSCI5I9XbDrYFIsQ/gqKgtzDKy2ihJ2Y8STL ++yO4hyFPFjxc+Gg4/P2PpmT5CY2ty44M0BWs+JGW96CJPrrplf2lmQUQJj5LZY66X ++Z/4C9L7ZYtKZ+bs5SvU46yWugAvQZX22Xm9xLXWyVXRdx3bj+3M3fDnF9di/zdbh ++CgLx7oWPNrXc7FCajnn9AoIBAQD5FMYwRpw9NWT9WDxQwx+cSI4Icbd88ByTW63S ++LzeRwZA0J9/SfwO+aBRupzc9GkGXCiZcGMw3AGsCtig8yFlw8E5KnzN7KlftDMnM ++9NUxxzlR8VwKyLnZfG7sDTl057ZlUujnqhmt/F8F7dIy7FVO1dE/8nngA+FYTCOG ++UZdGjwyBDlDM0JJdUWGY3xslutcpCDN5mzSTKjy9drMvImAshRawxRF6WBpn7vr2 ++nC6vciqfx1Mzx1vyk0Jm0ilaydDdLMADjt/iL4Nkr0BEs4k+UzQiKDwp8gu7abQ1 ++eBfxd9Iar4htQa2I1Ewl6P01G/q+ZYwgHhJ9RVn4AxQXefILAoIBAQDvCouORdQX ++C8wsyp7MwXlF/3NQeNN5/+B2mhbxrBOf7PmMCXLnkRWcjwJtzypWFqJ0sqai/2+0 ++bqbMcjX5maT8stT2shl3zXe/Ejt2e3TBYpc1tyuses8Kb5BMU8hu6tTd3G2CMXpD ++dT6DVemJZCTtwj9aBNIxSizvlgMolJnCpzhPnlfHSI6E+g3m/LTTo3HwbjMSw/Uq ++irgjOpI2wSBB6LZPSgjvfcYPRyWUk16L4A5uSX0cADnovDFLa5/h0wJvN/OoCSQg ++rLCXG5E18EyL5Wc58BCY1ZvxmjG3lQtgPxYu2Jwc36R/y/JKlxW5suER5ZNpbbD4 ++uOyTt2VxMQ2bAoIBAQC5+MzRFqdo/AjfL5Y5JrbfVTzXCTDa09xCGd16ZU60QTWN +++4ed/r+o1sUKqUcRFB2MzEM/2DQBjQpZB/CbEWvWa1XJWXxypXbowveZU+QqOnmN ++uQvj8WLyA3o+PNF9e9QvauwCrHpn8VpxbtPWuaYoKnUFreFZZQxHhPGxRBIS2JOZ ++eDrT8ZaWnkCkh1AZp5smQ71LOprSlmKrg4jd1GjCVMxQR5N5KXbtyv0OTCZ/UFqK ++2aRBsMPyJgkaBChkZPLRcKwc+/wlQRx1fHQb14DNTApMxoXFO7eOwqmOkpAt9iyl ++SBIwoS0UUI5ab88+bBmXNvKcuFdNuQ4nowTJUn9pAoIBADMNkILBXSvS5DeIyuO2 ++Sp1tkoZUV+5NfPY3sMDK3KIibaW/+t+EOBZo4L7tKQCb8vRzl21mmsfxfgRaPDbj ++3r3tv9g0b4YLxxBy52pFscj/soXRai17SS7UZwA2QK+XzgDYbDcLNC6mIsTQG4Gx ++dsWk3/zs3KuUSQaehmwrWK+fIUK38c1pLK8v7LoxrLkqxlHwZ04RthHw8KTthH7X ++Pnl1J0LF8CSeOyfWLSuPUfkT0GEzptnNHpEbaHfQM6R6eaGhVJPF6AZme4y6YYgg ++m2ihhSt1n0XVEWpHYWjxFy3mK2mz75unFC4LM+NEY2p2zuUQoCw7NjnY3QYrfCnx ++rRMCggEAXeXsMSLFjjyuoL7iKbAxo52HD/P0fBoy58LyRcwfNVr0lvYan4pYEx+o ++KijIh9K16PqXZXKMA9v003B+ulmF8bJ7SddCZ5NGvnFhUTDe4DdTKgp2RuwQ3Bsc ++3skPIDbhVETyOLCtys34USHrq8U/0DlGY3eLRfxw9GnbKxSBGa/KEu/qQLPNUo50 ++7xHZDg7GKeC3kqNJeqKM9rkp0VzIGkEnaD9127LeNDmERDfftxJzFoC/THvUBLfU ++6Sus2ZYwRE8VFvKC30Q45t/c54X3IuhYvAuiCuTmyfE4ruyzyOwKzhUkeeLq1APX ++g0veFbyfzlJ0q8qzD/iffqqIa2ZSmQ== ++-----END PRIVATE KEY----- +diff --git a/qtbase/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp b/qtbase/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp +index 7ba3715e13..752aa122f6 100644 +--- a/qtbase/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp ++++ b/qtbase/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp +@@ -179,6 +179,7 @@ void tst_QAccessibilityLinux::initTestCase() + QVERIFY(!address.isEmpty()); + + m_window = new AccessibleTestWindow(); ++ m_window->setObjectName("mainWindow"_L1); + m_window->show(); + + QVERIFY(QTest::qWaitForWindowExposed(m_window)); +@@ -236,8 +237,11 @@ bool hasState(QDBusInterface *interface, AtspiStateType state) + void tst_QAccessibilityLinux::testLabel() + { + QLabel *l = new QLabel(m_window); ++ l->setObjectName("theObjectName"_L1); + l->setText("Hello A11y"); + m_window->addWidget(l); ++ auto a11yEmpty = new QLabel(m_window); ++ m_window->addWidget(l); + + // Application + QCOMPARE(getParent(mainWindow), QLatin1String(ATSPI_DBUS_PATH_ROOT)); +@@ -249,6 +253,8 @@ void tst_QAccessibilityLinux::testLabel() + QCOMPARE(getChildren(labelInterface).count(), 0); + QCOMPARE(labelInterface->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("label")); + QCOMPARE(labelInterface->call(QDBus::Block, "GetRole").arguments().first().toUInt(), 29u); ++ QCOMPARE(labelInterface->call(QDBus::Block, "GetAccessibleId").arguments().first().toString(), ++ QLatin1String("mainWindow.theObjectName")); + QCOMPARE(getParent(labelInterface), mainWindow->path()); + QVERIFY(!hasState(labelInterface, ATSPI_STATE_EDITABLE)); + QVERIFY(hasState(labelInterface, ATSPI_STATE_READ_ONLY)); +@@ -256,7 +262,12 @@ void tst_QAccessibilityLinux::testLabel() + l->setText("New text"); + QCOMPARE(labelInterface->property("Name").toString(), l->text()); + ++ auto *a11yEmptyInterface = getInterface(children.at(1), "org.a11y.atspi.Accessible"); ++ QCOMPARE(a11yEmptyInterface->call(QDBus::Block, "GetAccessibleId").arguments().first().toString(), ++ QLatin1String("mainWindow.QLabel")); ++ + m_window->clearChildren(); ++ delete a11yEmptyInterface; + delete labelInterface; + } + +diff --git a/qtbase/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/qtbase/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp +index 76df61c892..6d6d65b791 100644 +--- a/qtbase/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp ++++ b/qtbase/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp +@@ -1,6 +1,6 @@ + /**************************************************************************** + ** +-** Copyright (C) 2016 The Qt Company Ltd. ++** Copyright (C) 2022 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the test suite of the Qt Toolkit. +@@ -68,6 +68,8 @@ private slots: + void query_exec(); + void execErrorRecovery_data() { generic_data(); } + void execErrorRecovery(); ++ void prematureExec_data() { generic_data(); } ++ void prematureExec(); + void first_data() { generic_data(); } + void first(); + void next_data() { generic_data(); } +@@ -2770,6 +2772,35 @@ void tst_QSqlQuery::execErrorRecovery() + QVERIFY_SQL( q, exec() ); + } + ++void tst_QSqlQuery::prematureExec() ++{ ++ QFETCH(QString, dbName); ++ // We only want the engine name, for addDatabase(): ++ int cut = dbName.indexOf(QChar('@')); ++ if (cut < 0) ++ QSKIP("Failed to parse database type out of name"); ++ dbName.truncate(cut); ++ cut = dbName.indexOf(QChar('_')); ++ if (cut >= 0) ++ dbName = dbName.mid(cut + 1); ++ ++ auto db = QSqlDatabase::addDatabase(dbName); ++ QSqlQuery q(db); ++ ++ QTest::ignoreMessage(QtWarningMsg, ++ "QSqlDatabasePrivate::removeDatabase: connection " ++ "'qt_sql_default_connection' is still in use, all " ++ "queries will cease to work."); ++ QTest::ignoreMessage(QtWarningMsg, ++ "QSqlDatabasePrivate::addDatabase: duplicate connection name " ++ "'qt_sql_default_connection', old connection removed."); ++ auto otherDb = QSqlDatabase::addDatabase(dbName); ++ ++ QTest::ignoreMessage(QtWarningMsg, "QSqlQuery::exec: called before driver has been set up"); ++ // QTBUG-100037: shouldn't crash ! ++ QVERIFY(!q.exec("select stuff from TheVoid")); ++} ++ + void tst_QSqlQuery::lastInsertId() + { + QFETCH( QString, dbName ); +diff --git a/qtbase/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp b/qtbase/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp +index 4aa3f8d60b..d2050a61aa 100644 +--- a/qtbase/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp ++++ b/qtbase/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp +@@ -115,6 +115,10 @@ void tst_QAbstractItemModelTester::standardItemModelZeroColumns() + // QTBUG-92886 + model.insertRows(0, 5); + model.removeRows(1, 2); ++ ++ const QModelIndex parentIndex = model.index(0, 0); ++ model.insertRows(0, 5, parentIndex); ++ model.removeRows(1, 2, parentIndex); + } + + void tst_QAbstractItemModelTester::testInsertThroughProxy() +diff --git a/qtbase/tests/auto/tools/moc/allmocs_baseline_in.json b/qtbase/tests/auto/tools/moc/allmocs_baseline_in.json +index 12a4a22a19..ce518e78fb 100644 +--- a/qtbase/tests/auto/tools/moc/allmocs_baseline_in.json ++++ b/qtbase/tests/auto/tools/moc/allmocs_baseline_in.json +@@ -668,50 +668,6 @@ + "inputFile": "task192552.h", + "outputRevision": 67 + }, +- { +- "classes": [ +- { +- "className": "InlineSlotsWithThrowDeclaration", +- "object": true, +- "qualifiedClassName": "InlineSlotsWithThrowDeclaration", +- "slots": [ +- { +- "access": "public", +- "name": "a", +- "returnType": "void" +- }, +- { +- "access": "public", +- "name": "b", +- "returnType": "void" +- }, +- { +- "access": "public", +- "name": "c", +- "returnType": "void" +- }, +- { +- "access": "public", +- "name": "d", +- "returnType": "void" +- }, +- { +- "access": "public", +- "name": "e", +- "returnType": "void" +- } +- ], +- "superClasses": [ +- { +- "access": "public", +- "name": "QObject" +- } +- ] +- } +- ], +- "inputFile": "task189996.h", +- "outputRevision": 67 +- }, + { + "classes": [ + { +diff --git a/qtbase/tests/auto/tools/moc/moc.pro b/qtbase/tests/auto/tools/moc/moc.pro +index c324b3a8cd..4aceb78dc0 100644 +--- a/qtbase/tests/auto/tools/moc/moc.pro ++++ b/qtbase/tests/auto/tools/moc/moc.pro +@@ -15,7 +15,7 @@ cross_compile: DEFINES += MOC_CROSS_COMPILED + HEADERS += using-namespaces.h no-keywords.h task87883.h c-comments.h backslash-newlines.h oldstyle-casts.h \ + slots-with-void-template.h qinvokable.h namespaced-flags.h trigraphs.h \ + escapes-in-string-literals.h cstyle-enums.h qprivateslots.h gadgetwithnoenums.h \ +- dir-in-include-path.h single_function_keyword.h task192552.h task189996.h \ ++ dir-in-include-path.h single_function_keyword.h task192552.h \ + task234909.h task240368.h pure-virtual-signals.h cxx11-enums.h \ + cxx11-final-classes.h \ + cxx11-explicit-override-control.h \ +diff --git a/qtbase/tests/auto/tools/moc/task189996.h b/qtbase/tests/auto/tools/moc/task189996.h +deleted file mode 100644 +index f94a051b3a..0000000000 +--- a/qtbase/tests/auto/tools/moc/task189996.h ++++ /dev/null +@@ -1,47 +0,0 @@ +-/**************************************************************************** +-** +-** Copyright (C) 2016 The Qt Company Ltd. +-** Contact: https://www.qt.io/licensing/ +-** +-** This file is part of the test suite of the Qt Toolkit. +-** +-** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +-** Commercial License Usage +-** Licensees holding valid commercial Qt licenses may use this file in +-** accordance with the commercial license agreement provided with the +-** Software or, alternatively, in accordance with the terms contained in +-** a written agreement between you and The Qt Company. For licensing terms +-** and conditions see https://www.qt.io/terms-conditions. For further +-** information use the contact form at https://www.qt.io/contact-us. +-** +-** GNU General Public License Usage +-** Alternatively, this file may be used under the terms of the GNU +-** General Public License version 3 as published by the Free Software +-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +-** included in the packaging of this file. Please review the following +-** information to ensure the GNU General Public License requirements will +-** be met: https://www.gnu.org/licenses/gpl-3.0.html. +-** +-** $QT_END_LICENSE$ +-** +-****************************************************************************/ +-// inline functions can have throw declarations +- +-#ifndef TASK189996_H +-#define TASK189996_H +- +-#include +- +-class InlineSlotsWithThrowDeclaration : public QObject +-{ +- Q_OBJECT +- +-public slots: +- void a() throw() { } +- void b() const throw() { } +- void c() throw(); +- void d() throw(int) { } +- void e() const throw(int,double) { } +-}; +- +-#endif +diff --git a/qtbase/tests/auto/tools/moc/tst_moc.cpp b/qtbase/tests/auto/tools/moc/tst_moc.cpp +index c716aead21..15dd9e41e5 100644 +--- a/qtbase/tests/auto/tools/moc/tst_moc.cpp ++++ b/qtbase/tests/auto/tools/moc/tst_moc.cpp +@@ -631,7 +631,6 @@ public: + private slots: + void initTestCase(); + +- void slotWithException() throw(MyStruct); + void dontStripNamespaces(); + void oldStyleCasts(); + void warnOnExtraSignalSlotQualifiaction(); +@@ -673,7 +672,6 @@ private slots: + void templateGtGt(); + void qprivateslots(); + void qprivateproperties(); +- void inlineSlotsWithThrowDeclaration(); + void warnOnPropertyWithoutREAD(); + void constructors(); + void typenameWithUnsigned(); +@@ -784,12 +782,6 @@ void tst_Moc::initTestCase() + #endif + } + +-void tst_Moc::slotWithException() throw(MyStruct) +-{ +- // be happy +- QVERIFY(true); +-} +- + void tst_Moc::dontStripNamespaces() + { + Sender sender; +@@ -824,7 +816,7 @@ void tst_Moc::oldStyleCasts() + + QStringList args; + args << "-c" << "-x" << "c++" << "-Wold-style-cast" << "-I" << "." +- << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-std=c++11" << "-"; ++ << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-std=c++1z" << "-"; + proc.start("gcc", args); + QVERIFY(proc.waitForStarted()); + proc.write(mocOut); +@@ -894,7 +886,7 @@ void tst_Moc::inputFileNameWithDotsButNoExtension() + + QStringList args; + args << "-c" << "-x" << "c++" << "-I" << ".." +- << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-std=c++11" << "-"; ++ << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-std=c++1z" << "-"; + proc.start("gcc", args); + QVERIFY(proc.waitForStarted()); + proc.write(mocOut); +@@ -1174,7 +1166,7 @@ void tst_Moc::ignoreOptionClashes() + QStringList gccArgs; + gccArgs << "-c" << "-x" << "c++" << "-I" << ".." + << "-I" << qtIncludePath << "-I" << includeDir << "-o" << "/dev/null" +- << "-fPIC" << "-std=c++11" << "-"; ++ << "-fPIC" << "-std=c++1z" << "-"; + proc.start("gcc", gccArgs); + QVERIFY(proc.waitForStarted()); + proc.write(mocOut); +@@ -1593,21 +1585,6 @@ void tst_Moc::qprivateproperties() + + } + +-#include "task189996.h" +- +-void InlineSlotsWithThrowDeclaration::c() throw() {} +- +-void tst_Moc::inlineSlotsWithThrowDeclaration() +-{ +- InlineSlotsWithThrowDeclaration tst; +- const QMetaObject *mobj = tst.metaObject(); +- QVERIFY(mobj->indexOfSlot("a()") != -1); +- QVERIFY(mobj->indexOfSlot("b()") != -1); +- QVERIFY(mobj->indexOfSlot("c()") != -1); +- QVERIFY(mobj->indexOfSlot("d()") != -1); +- QVERIFY(mobj->indexOfSlot("e()") != -1); +-} +- + void tst_Moc::warnOnPropertyWithoutREAD() + { + #ifdef MOC_CROSS_COMPILED +@@ -1869,7 +1846,7 @@ void tst_Moc::notifyError() + + QStringList args; + args << "-c" << "-x" << "c++" << "-I" << "." +- << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-std=c++11" << "-"; ++ << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-std=c++1z" << "-"; + proc.start("gcc", args); + QVERIFY(proc.waitForStarted()); + proc.write(mocOut); +diff --git a/qtbase/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/qtbase/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp +index c355ee9665..88c09de8e0 100644 +--- a/qtbase/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp ++++ b/qtbase/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp +@@ -251,6 +251,7 @@ private slots: + void testResetCachedSizeHint(); + void statusTips(); + void testRemovingColumnsViaLayoutChanged(); ++ void testModelMovingColumns(); + + protected: + void setupTestData(bool use_reset_model = false); +@@ -360,6 +361,12 @@ public: + endRemoveColumns(); + } + ++ void moveColumn(int from, int to) ++ { ++ beginMoveColumns(QModelIndex(), from, from, QModelIndex(), to); ++ endMoveColumns(); ++ } ++ + void cleanup() + { + emit layoutAboutToBeChanged(); +@@ -3627,5 +3634,18 @@ void tst_QHeaderView::testRemovingColumnsViaLayoutChanged() + // The main point of this test is that the section-size restoring code didn't go out of bounds. + } + ++void tst_QHeaderView::testModelMovingColumns() ++{ ++ QtTestModel model(10, 10); ++ QHeaderView hv(Qt::Horizontal); ++ hv.setModel(&model); ++ hv.resizeSections(QHeaderView::ResizeToContents); ++ hv.show(); ++ ++ QPersistentModelIndex index3 = model.index(0, 3); ++ model.moveColumn(3, 1); ++ QCOMPARE(index3.column(), 1); ++} ++ + QTEST_MAIN(tst_QHeaderView) + #include "tst_qheaderview.moc" +diff --git a/qtbase/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/qtbase/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp +index 761357b252..06bb706074 100644 +--- a/qtbase/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp ++++ b/qtbase/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp +@@ -397,6 +397,7 @@ private slots: + void checkHeaderMinSize(); + + void resizeToContents(); ++ void resizeToContentsSpans(); + + void tabFocus(); + void bigModel(); +@@ -3721,6 +3722,70 @@ void tst_QTableView::resizeToContents() + + } + ++ ++class SpanModel : public QAbstractTableModel ++{ ++public: ++ SpanModel(bool sectionsMoved) ++ : _sectionsMoved(sectionsMoved) ++ {} ++ int columnCount(const QModelIndex & = {}) const override { return 2; } ++ int rowCount(const QModelIndex & = {}) const override { return 1; } ++ QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override ++ { ++ if (role != Qt::DisplayRole) ++ return QVariant(); ++ const int col = _sectionsMoved ? 1 - idx.column() : idx.column(); ++ if (col == 0) ++ return "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; ++ return QVariant(); ++ } ++private: ++ bool _sectionsMoved; ++}; ++ ++ ++void tst_QTableView::resizeToContentsSpans() ++{ ++ SpanModel model1(false); ++ SpanModel model2(true); ++ QTableView view1, view2, view3; ++ view1.setModel(&model1); ++ view2.setModel(&model2); ++ view2.horizontalHeader()->moveSection(0, 1); ++ view3.setModel(&model1); ++ ++ view1.setSpan(0, 0, 1, 2); ++ view2.setSpan(0, 1, 1, 2); ++ view1.show(); ++ view2.show(); ++ view3.show(); ++ QVERIFY(QTest::qWaitForWindowExposed(&view1)); ++ QVERIFY(QTest::qWaitForWindowExposed(&view2)); ++ QVERIFY(QTest::qWaitForWindowExposed(&view3)); ++ view1.setColumnWidth(0, 100); ++ view1.setColumnWidth(1, 100); ++ view2.setColumnWidth(0, 100); ++ view2.setColumnWidth(1, 100); ++ view3.setColumnWidth(0, 200); ++ ++ view1.resizeRowToContents(0); ++ view2.resizeRowToContents(0); ++ view3.resizeRowToContents(0); ++ QCOMPARE(view1.rowHeight(0), view3.rowHeight(0)); ++ QCOMPARE(view2.rowHeight(0), view3.rowHeight(0)); ++ ++ view3.resizeColumnToContents(0); ++ view3.resizeRowToContents(0); ++ // height should be only 1 text line for easy testing ++ view1.setRowHeight(0, view3.verticalHeader()->sectionSize(0)); ++ view2.setRowHeight(0, view3.verticalHeader()->sectionSize(0)); ++ view1.resizeColumnToContents(0); ++ view2.resizeColumnToContents(1); ++ QCOMPARE(view1.columnWidth(0), view3.columnWidth(0) - view1.columnWidth(1)); ++ QCOMPARE(view2.columnWidth(0), view3.columnWidth(0) - view2.columnWidth(1)); ++} ++ + QT_BEGIN_NAMESPACE + extern bool Q_WIDGETS_EXPORT qt_tab_all_widgets(); // qapplication.cpp + QT_END_NAMESPACE +diff --git a/qtbase/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/qtbase/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +index a3b8ef78d8..4955cebd5d 100644 +--- a/qtbase/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp ++++ b/qtbase/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +@@ -1498,7 +1498,7 @@ void tst_QApplication::desktopSettingsAware() + environment += QLatin1String("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM=1"); + testProcess.setEnvironment(environment); + #endif +- testProcess.start("desktopsettingsaware_helper"); ++ testProcess.start("./desktopsettingsaware_helper"); + QVERIFY2(testProcess.waitForStarted(), + qPrintable(QString::fromLatin1("Cannot start 'desktopsettingsaware_helper': %1").arg(testProcess.errorString()))); + QVERIFY(testProcess.waitForFinished(10000)); +@@ -2452,7 +2452,7 @@ void tst_QApplication::qtbug_12673() + #if QT_CONFIG(process) + QProcess testProcess; + QStringList arguments; +- testProcess.start("modal_helper", arguments); ++ testProcess.start("./modal_helper", arguments); + QVERIFY2(testProcess.waitForStarted(), + qPrintable(QString::fromLatin1("Cannot start 'modal_helper': %1").arg(testProcess.errorString()))); + QVERIFY(testProcess.waitForFinished(20000)); +diff --git a/qtbase/tests/auto/widgets/widgets/qabstractbutton/tst_qabstractbutton.cpp b/qtbase/tests/auto/widgets/widgets/qabstractbutton/tst_qabstractbutton.cpp +index eb108a40de..dca5528c1b 100644 +--- a/qtbase/tests/auto/widgets/widgets/qabstractbutton/tst_qabstractbutton.cpp ++++ b/qtbase/tests/auto/widgets/widgets/qabstractbutton/tst_qabstractbutton.cpp +@@ -41,6 +41,7 @@ + + #include + #include ++#include + + class tst_QAbstractButton : public QObject + { +@@ -76,6 +77,8 @@ private slots: + void keyNavigation(); + #endif + ++ void buttonPressKeys(); ++ + protected slots: + void onClicked(); + void onToggled( bool on ); +@@ -269,7 +272,13 @@ void tst_QAbstractButton::setAutoRepeat() + QCOMPARE(press_count, click_count); + QVERIFY(click_count > 1); + break; +- case 4: ++ case 4: { ++ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() ++ ->themeHint(QPlatformTheme::ButtonPressKeys) ++ .value>(); ++ if (buttonPressKeys.contains(Qt::Key_Enter)) { ++ QSKIP("platform theme has Key_Enter in ButtonPressKeys"); ++ } + // check that pressing ENTER has no effect when autorepeat is false + testWidget->setDown( false ); + testWidget->setAutoRepeat( false ); +@@ -286,7 +295,14 @@ void tst_QAbstractButton::setAutoRepeat() + + QVERIFY( click_count == 0 ); + break; +- case 5: ++ } ++ case 5: { ++ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() ++ ->themeHint(QPlatformTheme::ButtonPressKeys) ++ .value>(); ++ if (buttonPressKeys.contains(Qt::Key_Enter)) { ++ QSKIP("platform theme has Key_Enter in ButtonPressKeys"); ++ } + // check that pressing ENTER has no effect when autorepeat is true + testWidget->setDown( false ); + testWidget->setAutoRepeat( true ); +@@ -304,6 +320,7 @@ void tst_QAbstractButton::setAutoRepeat() + + QVERIFY( click_count == 0 ); + break; ++ } + case 6: + // verify autorepeat is off by default. + MyButton tmp( 0); +@@ -651,5 +668,16 @@ void tst_QAbstractButton::keyNavigation() + } + #endif + ++void tst_QAbstractButton::buttonPressKeys() ++{ ++ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() ++ ->themeHint(QPlatformTheme::ButtonPressKeys) ++ .value>(); ++ for (int i = 0; i < buttonPressKeys.length(); ++i) { ++ QTest::keyClick(testWidget, buttonPressKeys[i]); ++ QCOMPARE(click_count, i + 1); ++ } ++} ++ + QTEST_MAIN(tst_QAbstractButton) + #include "tst_qabstractbutton.moc" +diff --git a/qtbase/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/qtbase/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp +index 32437050f5..46b5af6d63 100644 +--- a/qtbase/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp ++++ b/qtbase/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp +@@ -168,6 +168,7 @@ private slots: + void checkMenuItemPosWhenStyleSheetIsSet(); + void checkEmbeddedLineEditWhenStyleSheetIsSet(); + void propagateStyleChanges(); ++ void buttonPressKeys(); + + private: + PlatformInputContext m_platformInputContext; +@@ -1682,6 +1683,16 @@ void tst_QComboBox::setModel() + QCOMPARE(box.rootModelIndex(), rootModelIndex); + box.setModel(box.model()); + QCOMPARE(box.rootModelIndex(), rootModelIndex); ++ ++ // check that setting the same model as the completer's doesn't crash ++ QCompleter *completer = new QCompleter(&box); ++ box.setEditable(true); ++ box.setCompleter(completer); ++ auto *listModel = new QStringListModel({ "one", "two" }, completer); ++ completer->setModel(listModel); ++ QCOMPARE(listModel->rowCount(), 2); // make sure it wasn't deleted ++ box.setModel(listModel); ++ QCOMPARE(listModel->rowCount(), 2); // make sure it wasn't deleted + } + + void tst_QComboBox::setCustomModelAndView() +@@ -3632,5 +3643,24 @@ void tst_QComboBox::propagateStyleChanges() + QVERIFY(frameStyle.inquired); + } + ++void tst_QComboBox::buttonPressKeys() ++{ ++ QComboBox comboBox; ++ comboBox.setEditable(false); ++ comboBox.addItem(QString::number(1)); ++ comboBox.addItem(QString::number(2)); ++ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() ++ ->themeHint(QPlatformTheme::ButtonPressKeys) ++ .value>(); ++ for (int i = 0; i < buttonPressKeys.length(); ++i) { ++ QTest::keyClick(&comboBox, buttonPressKeys[i]); ++ // On some platforms, a window will not be immediately visible, ++ // but take some event-loop iterations to complete. ++ // Using QTRY_VERIFY to deal with that. ++ QTRY_VERIFY(comboBox.view()->isVisible()); ++ comboBox.hidePopup(); ++ } ++} ++ + QTEST_MAIN(tst_QComboBox) + #include "tst_qcombobox.moc" +diff --git a/qtbase/tests/auto/widgets/widgets/qcommandlinkbutton/qcommandlinkbutton.pro b/qtbase/tests/auto/widgets/widgets/qcommandlinkbutton/qcommandlinkbutton.pro +index be3cfcd104..c228fdfcca 100644 +--- a/qtbase/tests/auto/widgets/widgets/qcommandlinkbutton/qcommandlinkbutton.pro ++++ b/qtbase/tests/auto/widgets/widgets/qcommandlinkbutton/qcommandlinkbutton.pro +@@ -1,6 +1,6 @@ + CONFIG += testcase + TARGET = tst_qcommandlinkbutton +-QT += widgets testlib ++QT += widgets testlib gui-private + SOURCES += tst_qcommandlinkbutton.cpp + + +diff --git a/qtbase/tests/auto/widgets/widgets/qcommandlinkbutton/tst_qcommandlinkbutton.cpp b/qtbase/tests/auto/widgets/widgets/qcommandlinkbutton/tst_qcommandlinkbutton.cpp +index 0044d33c66..4cf06296e4 100644 +--- a/qtbase/tests/auto/widgets/widgets/qcommandlinkbutton/tst_qcommandlinkbutton.cpp ++++ b/qtbase/tests/auto/widgets/widgets/qcommandlinkbutton/tst_qcommandlinkbutton.cpp +@@ -40,6 +40,9 @@ + #include + #include + ++#include ++#include ++ + class tst_QCommandLinkButton : public QObject + { + Q_OBJECT +@@ -223,6 +226,13 @@ void tst_QCommandLinkButton::setAutoRepeat() + // check that pressing ENTER has no effect + resetCounters(); + testWidget->setDown( false ); ++ // Skip after reset if ButtonPressKeys has Key_Enter ++ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() ++ ->themeHint(QPlatformTheme::ButtonPressKeys) ++ .value>(); ++ if (buttonPressKeys.contains(Qt::Key_Enter)) { ++ return; ++ } + testWidget->setAutoRepeat( false ); + QTest::keyPress( testWidget, Qt::Key_Enter ); + +@@ -255,6 +265,14 @@ void tst_QCommandLinkButton::pressed() + QCOMPARE( press_count, (uint)1 ); + QCOMPARE( release_count, (uint)1 ); + ++ // Skip if ButtonPressKeys has Key_Enter ++ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() ++ ->themeHint(QPlatformTheme::ButtonPressKeys) ++ .value>(); ++ if (buttonPressKeys.contains(Qt::Key_Enter)) { ++ return; ++ } ++ + QTest::keyPress( testWidget,Qt::Key_Enter ); + QCOMPARE( press_count, (uint)1 ); + QCOMPARE( release_count, (uint)1 ); +diff --git a/qtbase/tests/auto/widgets/widgets/qgroupbox/qgroupbox.pro b/qtbase/tests/auto/widgets/widgets/qgroupbox/qgroupbox.pro +index 4a5e76ff65..a235fa1fac 100644 +--- a/qtbase/tests/auto/widgets/widgets/qgroupbox/qgroupbox.pro ++++ b/qtbase/tests/auto/widgets/widgets/qgroupbox/qgroupbox.pro +@@ -1,6 +1,6 @@ + CONFIG += testcase + TARGET = tst_qgroupbox +-QT += widgets testlib ++QT += widgets testlib gui-private + SOURCES += tst_qgroupbox.cpp + + +diff --git a/qtbase/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp b/qtbase/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp +index 4fb5d262ca..d8d7562b73 100644 +--- a/qtbase/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp ++++ b/qtbase/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp +@@ -35,6 +35,9 @@ + #include + #include + ++#include ++#include ++ + #include "qgroupbox.h" + + class tst_QGroupBox : public QObject +@@ -69,6 +72,7 @@ private slots: + void propagateFocus(); + void task_QTBUG_19170_ignoreMouseReleaseEvent(); + void task_QTBUG_15519_propagateMouseEvents(); ++ void buttonPressKeys(); + + private: + bool checked; +@@ -610,6 +614,20 @@ void tst_QGroupBox::task_QTBUG_15519_propagateMouseEvents() + QCOMPARE(parent.mouseMoved, true); + } + ++void tst_QGroupBox::buttonPressKeys() ++{ ++ QGroupBox groupBox; ++ groupBox.setCheckable(true); ++ QSignalSpy clickedSpy(&groupBox, &QGroupBox::clicked); ++ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() ++ ->themeHint(QPlatformTheme::ButtonPressKeys) ++ .value>(); ++ for (int i = 0; i < buttonPressKeys.length(); ++i) { ++ QTest::keyClick(&groupBox, buttonPressKeys[i]); ++ QCOMPARE(clickedSpy.length(), i + 1); ++ } ++} ++ + void tst_QGroupBox::sendMouseMoveEvent(QWidget *widget, const QPoint &localPos) + { + // Send a MouseMove event without actually moving the pointer +diff --git a/qtbase/tests/auto/widgets/widgets/qpushbutton/qpushbutton.pro b/qtbase/tests/auto/widgets/widgets/qpushbutton/qpushbutton.pro +index 353ad06ca2..e55f6148f2 100644 +--- a/qtbase/tests/auto/widgets/widgets/qpushbutton/qpushbutton.pro ++++ b/qtbase/tests/auto/widgets/widgets/qpushbutton/qpushbutton.pro +@@ -1,6 +1,6 @@ + CONFIG += testcase + TARGET = tst_qpushbutton +-QT += widgets testlib ++QT += widgets testlib gui-private + SOURCES += tst_qpushbutton.cpp + + +diff --git a/qtbase/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp b/qtbase/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp +index e818514a79..4043e9326a 100644 +--- a/qtbase/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp ++++ b/qtbase/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp +@@ -41,6 +41,9 @@ + #include + #include + ++#include ++#include ++ + class tst_QPushButton : public QObject + { + Q_OBJECT +@@ -212,6 +215,13 @@ void tst_QPushButton::autoRepeat() + // check that pressing ENTER has no effect + resetCounters(); + testWidget->setDown( false ); ++ // Skip after reset if ButtonPressKeys has Key_Enter ++ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() ++ ->themeHint(QPlatformTheme::ButtonPressKeys) ++ .value>(); ++ if (buttonPressKeys.contains(Qt::Key_Enter)) { ++ return; ++ } + testWidget->setAutoRepeat( false ); + QTest::keyPress( testWidget, Qt::Key_Enter ); + +@@ -247,6 +257,14 @@ void tst_QPushButton::pressed() + QCOMPARE( press_count, (uint)1 ); + QCOMPARE( release_count, (uint)1 ); + ++ // Skip if ButtonPressKeys has Key_Enter ++ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() ++ ->themeHint(QPlatformTheme::ButtonPressKeys) ++ .value>(); ++ if (buttonPressKeys.contains(Qt::Key_Enter)) { ++ return; ++ } ++ + QTest::keyPress( testWidget,Qt::Key_Enter ); + QCOMPARE( press_count, (uint)1 ); + QCOMPARE( release_count, (uint)1 ); +diff --git a/qtbase/tests/manual/rhi/cubemap_render/buildshader.bat b/qtbase/tests/manual/rhi/cubemap_render/buildshader.bat +old mode 100755 +new mode 100644 +Submodule qtconnectivity e957d481..056294c0: +diff --git a/qtconnectivity/src/bluetooth/bluez/hcimanager.cpp b/qtconnectivity/src/bluetooth/bluez/hcimanager.cpp +index e2635fae..a8b8e3b9 100644 +--- a/qtconnectivity/src/bluetooth/bluez/hcimanager.cpp ++++ b/qtconnectivity/src/bluetooth/bluez/hcimanager.cpp +@@ -563,9 +563,11 @@ void HciManager::handleHciAclPacket(const quint8 *data, int size) + + void HciManager::handleLeMetaEvent(const quint8 *data) + { +- // Spec v4.2, Vol 2, part E, 7.7.65ff ++ // Spec v5.3, Vol 4, part E, 7.7.65.* + switch (*data) { +- case 0x1: { ++ case 0x1: // HCI_LE_Connection_Complete ++ case 0xA: // HCI_LE_Enhanced_Connection_Complete ++ { + const quint16 handle = bt_get_le16(data + 2); + emit connectionComplete(handle); + break; +diff --git a/qtconnectivity/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp b/qtconnectivity/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp +index 6a93143b..4a18cfc7 100644 +--- a/qtconnectivity/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp ++++ b/qtconnectivity/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp +@@ -320,7 +320,10 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_finishSdpScan(QBluetoothServiceD + for (const QBluetoothUuid &id : serviceClassUuids) { + if (id.minimumSize() == 16) { + serviceInfo.setServiceUuid(id); +- serviceInfo.setServiceName(QBluetoothServiceDiscoveryAgent::tr("Custom Service")); ++ if (serviceInfo.serviceName().isEmpty()) { ++ serviceInfo.setServiceName( ++ QBluetoothServiceDiscoveryAgent::tr("Custom Service")); ++ } + QBluetoothServiceInfo::Sequence modSeq = + serviceInfo.attribute(QBluetoothServiceInfo::ServiceClassIds).value(); + modSeq.removeOne(QVariant::fromValue(id)); +@@ -334,8 +337,10 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_finishSdpScan(QBluetoothServiceD + qCDebug(QT_BT_BLUEZ) << "Discovered services" << discoveredDevices.at(0).address().toString() + << serviceInfo.serviceName() << serviceInfo.serviceUuid() + << ">>>" << serviceInfo.serviceClassUuids(); +- +- emit q->serviceDiscovered(serviceInfo); ++ // Use queued connection to allow us finish the service looping; the application ++ // might call stop() when it has detected the service-of-interest. ++ QMetaObject::invokeMethod(q, "serviceDiscovered", Qt::QueuedConnection, ++ Q_ARG(QBluetoothServiceInfo, serviceInfo)); + } + } + } +diff --git a/qtconnectivity/src/bluetooth/qbluetoothsocket.cpp b/qtconnectivity/src/bluetooth/qbluetoothsocket.cpp +index e4d85447..aadd4755 100644 +--- a/qtconnectivity/src/bluetooth/qbluetoothsocket.cpp ++++ b/qtconnectivity/src/bluetooth/qbluetoothsocket.cpp +@@ -593,7 +593,7 @@ void QBluetoothSocket::setSocketState(QBluetoothSocket::SocketState state) + bool QBluetoothSocket::canReadLine() const + { + Q_D(const QBluetoothSocketBase); +- return d->canReadLine(); ++ return d->canReadLine() || QIODevice::canReadLine(); + } + + /*! +diff --git a/qtconnectivity/src/bluetooth/qbluetoothsocket_bluezdbus.cpp b/qtconnectivity/src/bluetooth/qbluetoothsocket_bluezdbus.cpp +index 084aa958..d6aa17a7 100644 +--- a/qtconnectivity/src/bluetooth/qbluetoothsocket_bluezdbus.cpp ++++ b/qtconnectivity/src/bluetooth/qbluetoothsocket_bluezdbus.cpp +@@ -284,6 +284,10 @@ void QBluetoothSocketPrivateBluezDBus::connectToService( + return; + } + ++ if (service.socketProtocol() != QBluetoothServiceInfo::Protocol::UnknownProtocol) ++ socketType = service.socketProtocol(); ++ qCDebug(QT_BT_BLUEZ) << "Socket protocol used:" << socketType; ++ + connectToService(service.device().address(), targetService, openMode); + } + +diff --git a/qtconnectivity/tests/auto/qbluetoothsocket/tst_qbluetoothsocket.cpp b/qtconnectivity/tests/auto/qbluetoothsocket/tst_qbluetoothsocket.cpp +index 05bc1a0f..a7b5ef1f 100644 +--- a/qtconnectivity/tests/auto/qbluetoothsocket/tst_qbluetoothsocket.cpp ++++ b/qtconnectivity/tests/auto/qbluetoothsocket/tst_qbluetoothsocket.cpp +@@ -142,7 +142,7 @@ void tst_QBluetoothSocket::initTestCase() + qDebug() << "Starting discovery"; + + sda->setUuidFilter(QBluetoothUuid(QString(TEST_SERVICE_UUID))); +- sda->start(QBluetoothServiceDiscoveryAgent::MinimalDiscovery); ++ sda->start(QBluetoothServiceDiscoveryAgent::FullDiscovery); + + for (int connectTime = MaxConnectTime; !done_discovery && connectTime > 0; connectTime -= 1000) + QTest::qWait(1000); +Submodule qtdeclarative f5701f0d..8defe7bf: +diff --git a/qtdeclarative/src/qml/common/qqmljsfixedpoolarray_p.h b/qtdeclarative/src/qml/common/qqmljsfixedpoolarray_p.h +index b65b994d6c..15a8cd6878 100644 +--- a/qtdeclarative/src/qml/common/qqmljsfixedpoolarray_p.h ++++ b/qtdeclarative/src/qml/common/qqmljsfixedpoolarray_p.h +@@ -86,7 +86,7 @@ public: + if (QTypeInfo::isComplex) { + for (int i = 0; i < count; ++i) + new (data + i) T(vector.at(i)); +- } else { ++ } else if (count) { + memcpy(data, static_cast(vector.constData()), count * sizeof(T)); + } + } +diff --git a/qtdeclarative/src/qml/jsruntime/qv4qobjectwrapper.cpp b/qtdeclarative/src/qml/jsruntime/qv4qobjectwrapper.cpp +index e57cdd8278..94613598af 100644 +--- a/qtdeclarative/src/qml/jsruntime/qv4qobjectwrapper.cpp ++++ b/qtdeclarative/src/qml/jsruntime/qv4qobjectwrapper.cpp +@@ -1145,8 +1145,7 @@ void Heap::QObjectWrapper::markObjects(Heap::Base *that, QV4::MarkStack *markSta + void QObjectWrapper::destroyObject(bool lastCall) + { + Heap::QObjectWrapper *h = d(); +- if (!h->internalClass) +- return; // destroyObject already got called ++ Q_ASSERT(h->internalClass); + + if (h->object()) { + QQmlData *ddata = QQmlData::get(h->object(), false); +@@ -1176,7 +1175,7 @@ void QObjectWrapper::destroyObject(bool lastCall) + } + } + +- h->~Data(); ++ h->destroy(); + } + + +diff --git a/qtdeclarative/src/qml/memory/qv4mm.cpp b/qtdeclarative/src/qml/memory/qv4mm.cpp +index 06caf04e5a..da149a67c4 100644 +--- a/qtdeclarative/src/qml/memory/qv4mm.cpp ++++ b/qtdeclarative/src/qml/memory/qv4mm.cpp +@@ -981,7 +981,7 @@ void MemoryManager::sweep(bool lastSweep, ClassDestroyStatsCallback classCountPt + + if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = engine->m_multiplyWrappedQObjects) { + for (MultiplyWrappedQObjectMap::Iterator it = multiplyWrappedQObjects->begin(); it != multiplyWrappedQObjects->end();) { +- if (!it.value().isNullOrUndefined()) ++ if (it.value().isNullOrUndefined()) + it = multiplyWrappedQObjects->erase(it); + else + ++it; +diff --git a/qtdeclarative/src/qmlmodels/qqmldelegatemodel.cpp b/qtdeclarative/src/qmlmodels/qqmldelegatemodel.cpp +index 2079a8ed04..a577cb2351 100644 +--- a/qtdeclarative/src/qmlmodels/qqmldelegatemodel.cpp ++++ b/qtdeclarative/src/qmlmodels/qqmldelegatemodel.cpp +@@ -389,6 +389,12 @@ void QQmlDelegateModelPrivate::connectToAbstractItemModel() + q, QQmlDelegateModel, SLOT(_q_rowsRemoved(QModelIndex,int,int))); + qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), + q, QQmlDelegateModel, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int))); ++ qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsInserted(QModelIndex,int,int)), ++ q, QQmlDelegateModel, SLOT(_q_columnsInserted(QModelIndex,int,int))); ++ qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsRemoved(QModelIndex,int,int)), ++ q, QQmlDelegateModel, SLOT(_q_columnsRemoved(QModelIndex,int,int))); ++ qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), ++ q, QQmlDelegateModel, SLOT(_q_columnsMoved(QModelIndex,int,int,QModelIndex,int))); + qmlobject_connect(aim, QAbstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector)), + q, QQmlDelegateModel, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector))); + qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), +@@ -413,6 +419,12 @@ void QQmlDelegateModelPrivate::disconnectFromAbstractItemModel() + q, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int))); + QObject::disconnect(aim, SIGNAL(rowsRemoved(QModelIndex,int,int)), + q, SLOT(_q_rowsRemoved(QModelIndex,int,int))); ++ QObject::disconnect(aim, SIGNAL(columnsInserted(QModelIndex,int,int)), q, ++ SLOT(_q_columnsInserted(QModelIndex,int,int))); ++ QObject::disconnect(aim, SIGNAL(columnsRemoved(QModelIndex,int,int)), q, ++ SLOT(_q_columnsRemoved(QModelIndex,int,int))); ++ QObject::disconnect(aim, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), q, ++ SLOT(_q_columnsMoved(QModelIndex,int,int,QModelIndex,int))); + QObject::disconnect(aim, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector)), + q, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector))); + QObject::disconnect(aim, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), +@@ -1973,6 +1985,38 @@ void QQmlDelegateModel::_q_rowsMoved( + } + } + ++void QQmlDelegateModel::_q_columnsInserted(const QModelIndex &parent, int begin, int end) ++{ ++ Q_D(QQmlDelegateModel); ++ Q_UNUSED(end); ++ if (parent == d->m_adaptorModel.rootIndex && begin == 0) { ++ // mark all items as changed ++ _q_itemsChanged(0, d->m_count, QVector()); ++ } ++} ++ ++void QQmlDelegateModel::_q_columnsRemoved(const QModelIndex &parent, int begin, int end) ++{ ++ Q_D(QQmlDelegateModel); ++ Q_UNUSED(end); ++ if (parent == d->m_adaptorModel.rootIndex && begin == 0) { ++ // mark all items as changed ++ _q_itemsChanged(0, d->m_count, QVector()); ++ } ++} ++ ++void QQmlDelegateModel::_q_columnsMoved(const QModelIndex &parent, int start, int end, ++ const QModelIndex &destination, int column) ++{ ++ Q_D(QQmlDelegateModel); ++ Q_UNUSED(end); ++ if ((parent == d->m_adaptorModel.rootIndex && start == 0) ++ || (destination == d->m_adaptorModel.rootIndex && column == 0)) { ++ // mark all items as changed ++ _q_itemsChanged(0, d->m_count, QVector()); ++ } ++} ++ + void QQmlDelegateModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end, const QVector &roles) + { + Q_D(QQmlDelegateModel); +diff --git a/qtdeclarative/src/qmlmodels/qqmldelegatemodel_p.h b/qtdeclarative/src/qmlmodels/qqmldelegatemodel_p.h +index 8aab4badca..d140bfbaaf 100644 +--- a/qtdeclarative/src/qmlmodels/qqmldelegatemodel_p.h ++++ b/qtdeclarative/src/qmlmodels/qqmldelegatemodel_p.h +@@ -152,6 +152,9 @@ private Q_SLOTS: + void _q_itemsMoved(int from, int to, int count); + void _q_modelReset(); + void _q_rowsInserted(const QModelIndex &,int,int); ++ void _q_columnsInserted(const QModelIndex &, int, int); ++ void _q_columnsRemoved(const QModelIndex &, int, int); ++ void _q_columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int); + void _q_rowsAboutToBeRemoved(const QModelIndex &parent, int begin, int end); + void _q_rowsRemoved(const QModelIndex &,int,int); + void _q_rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int); +diff --git a/qtdeclarative/src/quick/accessible/qaccessiblequickitem.cpp b/qtdeclarative/src/quick/accessible/qaccessiblequickitem.cpp +index 85719fdc80..78e2ab302c 100644 +--- a/qtdeclarative/src/quick/accessible/qaccessiblequickitem.cpp ++++ b/qtdeclarative/src/quick/accessible/qaccessiblequickitem.cpp +@@ -46,6 +46,7 @@ + #include "QtQuick/private/qquicktextinput_p.h" + #include "QtQuick/private/qquickaccessibleattached_p.h" + #include "QtQuick/qquicktextdocument.h" ++#include "QtQuick/qquickrendercontrol.h" + QT_BEGIN_NAMESPACE + + #if QT_CONFIG(accessibility) +@@ -57,7 +58,19 @@ QAccessibleQuickItem::QAccessibleQuickItem(QQuickItem *item) + + QWindow *QAccessibleQuickItem::window() const + { +- return item()->window(); ++ QQuickWindow *window = item()->window(); ++ ++ // For QQuickWidget the above window will be the offscreen QQuickWindow, ++ // which is not a part of the accessibility tree. Detect this case and ++ // return the window for the QQuickWidget instead. ++ if (window && !window->handle()) { ++ if (QQuickRenderControl *renderControl = QQuickWindowPrivate::get(window)->renderControl) { ++ if (QWindow *renderWindow = renderControl->renderWindow(nullptr)) ++ return renderWindow; ++ } ++ } ++ ++ return window; + } + + int QAccessibleQuickItem::childCount() const +@@ -113,19 +126,15 @@ QAccessibleInterface *QAccessibleQuickItem::childAt(int x, int y) const + QAccessibleInterface *QAccessibleQuickItem::parent() const + { + QQuickItem *parent = item()->parentItem(); +- QQuickWindow *window = item()->window(); +- QQuickItem *ci = window ? window->contentItem() : nullptr; ++ QQuickWindow *itemWindow = item()->window(); ++ QQuickItem *ci = itemWindow ? itemWindow->contentItem() : nullptr; + while (parent && !QQuickItemPrivate::get(parent)->isAccessible && parent != ci) + parent = parent->parentItem(); + + if (parent) { + if (parent == ci) { +- // Jump out to the scene widget if the parent is the root item. +- // There are two root items, QQuickWindow::rootItem and +- // QQuickView::declarativeRoot. The former is the true root item, +- // but is not a part of the accessibility tree. Check if we hit +- // it here and return an interface for the scene instead. +- return QAccessible::queryAccessibleInterface(window); ++ // Jump out to the window if the parent is the root item ++ return QAccessible::queryAccessibleInterface(window()); + } else { + while (parent && !parent->d_func()->isAccessible) + parent = parent->parentItem(); +@@ -188,7 +197,7 @@ QAccessible::State QAccessibleQuickItem::state() const + QRect viewRect_ = viewRect(); + QRect itemRect = rect(); + +- if (viewRect_.isNull() || itemRect.isNull() || !item()->window() || !item()->window()->isVisible() ||!item()->isVisible() || qFuzzyIsNull(item()->opacity())) ++ if (viewRect_.isNull() || itemRect.isNull() || !window() || !window()->isVisible() ||!item()->isVisible() || qFuzzyIsNull(item()->opacity())) + state.invisible = true; + if (!viewRect_.intersects(itemRect)) + state.offscreen = true; +@@ -201,6 +210,10 @@ QAccessible::State QAccessibleQuickItem::state() const + if (role() == QAccessible::EditableText) + if (auto ti = qobject_cast(item())) + state.passwordEdit = ti->echoMode() != QQuickTextInput::Normal; ++ if (!item()->isEnabled()) { ++ state.focusable = false; ++ state.disabled = true; ++ } + return state; + } + +diff --git a/qtdeclarative/src/quick/accessible/qaccessiblequickview_p.h b/qtdeclarative/src/quick/accessible/qaccessiblequickview_p.h +index 39ffcaf39c..8baa01330c 100644 +--- a/qtdeclarative/src/quick/accessible/qaccessiblequickview_p.h ++++ b/qtdeclarative/src/quick/accessible/qaccessiblequickview_p.h +@@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE + + #if QT_CONFIG(accessibility) + +-class QAccessibleQuickWindow : public QAccessibleObject ++class Q_QUICK_EXPORT QAccessibleQuickWindow : public QAccessibleObject + { + public: + QAccessibleQuickWindow(QQuickWindow *object); +diff --git a/qtdeclarative/src/quick/items/qquickdrag.cpp b/qtdeclarative/src/quick/items/qquickdrag.cpp +index 8321fcfeed..383078b3b9 100644 +--- a/qtdeclarative/src/quick/items/qquickdrag.cpp ++++ b/qtdeclarative/src/quick/items/qquickdrag.cpp +@@ -481,7 +481,9 @@ void QQuickDragAttached::setKeys(const QStringList &keys) + \qmlattachedproperty stringlist QtQuick::Drag::mimeData + \since 5.2 + +- This property holds a map of mimeData that is used during startDrag. ++ This property holds a map from mime type to data that is used during startDrag. ++ The mime data needs to be a \c string, or an \c ArrayBuffer with the data encoded ++ according to the mime type. + */ + + QVariantMap QQuickDragAttached::mimeData() const +@@ -766,8 +768,12 @@ Qt::DropAction QQuickDragAttachedPrivate::startDrag(Qt::DropActions supportedAct + QDrag *drag = new QDrag(source ? source : q); + QMimeData *mimeData = new QMimeData(); + +- for (auto it = externalMimeData.cbegin(), end = externalMimeData.cend(); it != end; ++it) +- mimeData->setData(it.key(), it.value().toString().toUtf8()); ++ for (auto it = externalMimeData.cbegin(), end = externalMimeData.cend(); it != end; ++it) { ++ if (static_cast(it.value().type()) == QMetaType::QByteArray) ++ mimeData->setData(it.key(), it.value().toByteArray()); ++ else ++ mimeData->setData(it.key(), it.value().toString().toUtf8()); ++ } + + drag->setMimeData(mimeData); + if (pixmapLoader.isReady()) { +diff --git a/qtdeclarative/src/quick/items/qquickitem.cpp b/qtdeclarative/src/quick/items/qquickitem.cpp +index 75f1457816..dec0ae19ae 100644 +--- a/qtdeclarative/src/quick/items/qquickitem.cpp ++++ b/qtdeclarative/src/quick/items/qquickitem.cpp +@@ -59,6 +59,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -2326,6 +2327,7 @@ QQuickItem::QQuickItem(QQuickItemPrivate &dd, QQuickItem *parent) + QQuickItem::~QQuickItem() + { + Q_D(QQuickItem); ++ d->inDestructor = true; + + if (d->windowRefCount > 1) + d->windowRefCount = 1; // Make sure window is set to null in next call to derefWindow(). +@@ -2526,6 +2528,7 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo + QQuickItem *current = item; + qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: startItem:" << startItem; + qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: firstFromItem:" << firstFromItem; ++ QDuplicateTracker cycleDetector; + do { + qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: current:" << current; + qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: from:" << from; +@@ -2592,7 +2595,10 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo + // traversed all of the chain (by compare the [current] item with [startItem]) + // Since the [startItem] might be promoted to its parent if it is invisible, + // we still have to check [current] item with original start item +- if ((current == startItem || current == originalStartItem) && from == firstFromItem) { ++ // We might also run into a cycle before we reach firstFromItem again ++ // but note that we have to ignore current if we are meant to skip it ++ if (((current == startItem || current == originalStartItem) && from == firstFromItem) || ++ (!skip && cycleDetector.hasSeen(current))) { + // wrapped around, avoid endless loops + if (item == contentItem) { + qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return contentItem"; +@@ -2689,9 +2695,8 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) + + const bool wasVisible = isVisible(); + op->removeChild(this); +- if (wasVisible) { ++ if (wasVisible && !op->inDestructor) + emit oldParentItem->visibleChildrenChanged(); +- } + } else if (d->window) { + QQuickWindowPrivate::get(d->window)->parentlessItems.remove(this); + } +@@ -2768,8 +2773,9 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) + + d->itemChange(ItemParentHasChanged, d->parentItem); + +- emit parentChanged(d->parentItem); +- if (isVisible() && d->parentItem) ++ if (!d->inDestructor) ++ emit parentChanged(d->parentItem); ++ if (isVisible() && d->parentItem && !QQuickItemPrivate::get(d->parentItem)->inDestructor) + emit d->parentItem->visibleChildrenChanged(); + } + +@@ -2965,7 +2971,8 @@ void QQuickItemPrivate::removeChild(QQuickItem *child) + + itemChange(QQuickItem::ItemChildRemovedChange, child); + +- emit q->childrenChanged(); ++ if (!inDestructor) ++ emit q->childrenChanged(); + } + + void QQuickItemPrivate::refWindow(QQuickWindow *c) +@@ -3194,6 +3201,7 @@ QQuickItemPrivate::QQuickItemPrivate() + , touchEnabled(false) + #endif + , hasCursorHandler(false) ++ , inDestructor(false) + , dirtyAttributes(0) + , nextDirtyItem(nullptr) + , prevDirtyItem(nullptr) +@@ -5120,6 +5128,13 @@ void QQuickItem::componentComplete() + d->addToDirtyList(); + QQuickWindowPrivate::get(d->window)->dirtyItem(this); + } ++ ++#if QT_CONFIG(accessibility) ++ if (d->isAccessible && d->effectiveVisible) { ++ QAccessibleEvent ev(this, QAccessible::ObjectShow); ++ QAccessible::updateAccessibility(&ev); ++ } ++#endif + } + + QQuickStateGroup *QQuickItemPrivate::_states() +@@ -6106,9 +6121,11 @@ bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible) + QAccessible::updateAccessibility(&ev); + } + #endif +- emit q->visibleChanged(); +- if (childVisibilityChanged) +- emit q->visibleChildrenChanged(); ++ if (!inDestructor) { ++ emit q->visibleChanged(); ++ if (childVisibilityChanged) ++ emit q->visibleChildrenChanged(); ++ } + + return true; // effective visibility DID change + } +@@ -6157,6 +6174,15 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec + } + + itemChange(QQuickItem::ItemEnabledHasChanged, effectiveEnable); ++#if QT_CONFIG(accessibility) ++ if (isAccessible) { ++ QAccessible::State changedState; ++ changedState.disabled = true; ++ changedState.focusable = true; ++ QAccessibleStateChangeEvent ev(q, changedState); ++ QAccessible::updateAccessibility(&ev); ++ } ++#endif + emit q->enabledChanged(); + } + +diff --git a/qtdeclarative/src/quick/items/qquickitem_p.h b/qtdeclarative/src/quick/items/qquickitem_p.h +index 841d91bb40..ade8fb61f2 100644 +--- a/qtdeclarative/src/quick/items/qquickitem_p.h ++++ b/qtdeclarative/src/quick/items/qquickitem_p.h +@@ -472,6 +472,7 @@ public: + bool replayingPressEvent:1; + bool touchEnabled:1; + bool hasCursorHandler:1; ++ quint32 inDestructor:1; // has entered ~QQuickItem + + enum DirtyType { + TransformOrigin = 0x00000001, +diff --git a/qtdeclarative/src/quick/items/qquickitemview.cpp b/qtdeclarative/src/quick/items/qquickitemview.cpp +index 010a0152e1..f8ad168a17 100644 +--- a/qtdeclarative/src/quick/items/qquickitemview.cpp ++++ b/qtdeclarative/src/quick/items/qquickitemview.cpp +@@ -1785,7 +1785,7 @@ void QQuickItemViewPrivate::refill(qreal from, qreal to) + + do { + bufferPause.stop(); +- if (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges()) { ++ if (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges() || currentChanges.active) { + currentChanges.reset(); + bufferedChanges.reset(); + releaseVisibleItems(reusableFlag); +diff --git a/qtdeclarative/src/quick/items/qquickmousearea_p_p.h b/qtdeclarative/src/quick/items/qquickmousearea_p_p.h +index fba383e268..0d63618622 100644 +--- a/qtdeclarative/src/quick/items/qquickmousearea_p_p.h ++++ b/qtdeclarative/src/quick/items/qquickmousearea_p_p.h +@@ -61,7 +61,6 @@ QT_BEGIN_NAMESPACE + + class QQuickMouseEvent; + class QQuickMouseArea; +-class QQuickPointerMask; + class QQuickMouseAreaPrivate : public QQuickItemPrivate + { + Q_DECLARE_PUBLIC(QQuickMouseArea) +@@ -100,7 +99,6 @@ public: + #if QT_CONFIG(quick_draganddrop) + QQuickDrag *drag; + #endif +- QPointer mask; + QPointF startScene; + QPointF targetStartPos; + QPointF lastPos; +diff --git a/qtdeclarative/src/quick/items/qquicktext.cpp b/qtdeclarative/src/quick/items/qquicktext.cpp +index 6230186933..e823ca1095 100644 +--- a/qtdeclarative/src/quick/items/qquicktext.cpp ++++ b/qtdeclarative/src/quick/items/qquicktext.cpp +@@ -2168,7 +2168,7 @@ void QQuickText::resetMaximumLineCount() + - inline images +
    ,
      and
    • - ordered and unordered lists +
       - preformatted
      +-    > < &
      ++    > < & "   '
      +     \endcode
      + 
      +     \c Text.StyledText parser is strict, requiring tags to be correctly nested.
      +diff --git a/qtdeclarative/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp b/qtdeclarative/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp
      +index eb4db0f85e..2325a2665b 100644
      +--- a/qtdeclarative/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp
      ++++ b/qtdeclarative/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp
      +@@ -446,7 +446,7 @@ bool QSGRhiDistanceFieldGlyphCache::loadPregeneratedCache(const QRawFont &font)
      + 
      +         const char *textureRecord = allocatorData;
      +         for (int i = 0; i < textureCount; ++i, textureRecord += Qtdf::TextureRecordSize) {
      +-            if (textureRecord + Qtdf::TextureRecordSize > qtdfTableEnd) {
      ++            if (qtdfTableEnd - textureRecord < Qtdf::TextureRecordSize) {
      +                 qWarning("qtdf table too small in font '%s'.",
      +                          qPrintable(font.familyName()));
      +                 return false;
      +@@ -462,7 +462,7 @@ bool QSGRhiDistanceFieldGlyphCache::loadPregeneratedCache(const QRawFont &font)
      + 
      +         const char *glyphRecord = textureRecord;
      +         for (quint32 i = 0; i < glyphCount; ++i, glyphRecord += Qtdf::GlyphRecordSize) {
      +-            if (glyphRecord + Qtdf::GlyphRecordSize > qtdfTableEnd) {
      ++            if (qtdfTableEnd - glyphRecord < Qtdf:: GlyphRecordSize) {
      +                 qWarning("qtdf table too small in font '%s'.",
      +                          qPrintable(font.familyName()));
      +                 return false;
      +@@ -512,8 +512,8 @@ bool QSGRhiDistanceFieldGlyphCache::loadPregeneratedCache(const QRawFont &font)
      + 
      +             int width = texInfo->allocatedArea.width();
      +             int height = texInfo->allocatedArea.height();
      +-            qint64 size = width * height;
      +-            if (reinterpret_cast(textureData + size) > qtdfTableEnd) {
      ++            qint64 size = qint64(width) * height;
      ++            if (qtdfTableEnd - reinterpret_cast(textureData) < size) {
      +                 qWarning("qtdf table too small in font '%s'.",
      +                          qPrintable(font.familyName()));
      +                 return false;
      +diff --git a/qtdeclarative/src/quick/util/qquickstyledtext.cpp b/qtdeclarative/src/quick/util/qquickstyledtext.cpp
      +index d531fc9205..a25af90414 100644
      +--- a/qtdeclarative/src/quick/util/qquickstyledtext.cpp
      ++++ b/qtdeclarative/src/quick/util/qquickstyledtext.cpp
      +@@ -564,6 +564,8 @@ void QQuickStyledTextPrivate::parseEntity(const QChar *&ch, const QString &textI
      +                 textOut += QChar(60);
      +             else if (entity == QLatin1String("amp"))
      +                 textOut += QChar(38);
      ++            else if (entity == QLatin1String("apos"))
      ++                textOut += QChar(39);
      +             else if (entity == QLatin1String("quot"))
      +                 textOut += QChar(34);
      +             else if (entity == QLatin1String("nbsp"))
      +diff --git a/qtdeclarative/src/quickwidgets/qaccessiblequickwidget.cpp b/qtdeclarative/src/quickwidgets/qaccessiblequickwidget.cpp
      +new file mode 100644
      +index 0000000000..8a1c901880
      +--- /dev/null
      ++++ b/qtdeclarative/src/quickwidgets/qaccessiblequickwidget.cpp
      +@@ -0,0 +1,110 @@
      ++/****************************************************************************
      ++**
      ++** Copyright (C) 2021 The Qt Company Ltd.
      ++** Contact: https://www.qt.io/licensing/
      ++**
      ++** This file is part of the QtQuick module of the Qt Toolkit.
      ++**
      ++** $QT_BEGIN_LICENSE:LGPL$
      ++** Commercial License Usage
      ++** Licensees holding valid commercial Qt licenses may use this file in
      ++** accordance with the commercial license agreement provided with the
      ++** Software or, alternatively, in accordance with the terms contained in
      ++** a written agreement between you and The Qt Company. For licensing terms
      ++** and conditions see https://www.qt.io/terms-conditions. For further
      ++** information use the contact form at https://www.qt.io/contact-us.
      ++**
      ++** GNU Lesser General Public License Usage
      ++** Alternatively, this file may be used under the terms of the GNU Lesser
      ++** General Public License version 3 as published by the Free Software
      ++** Foundation and appearing in the file LICENSE.LGPL3 included in the
      ++** packaging of this file. Please review the following information to
      ++** ensure the GNU Lesser General Public License version 3 requirements
      ++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
      ++**
      ++** GNU General Public License Usage
      ++** Alternatively, this file may be used under the terms of the GNU
      ++** General Public License version 2.0 or (at your option) the GNU General
      ++** Public license version 3 or any later version approved by the KDE Free
      ++** Qt Foundation. The licenses are as published by the Free Software
      ++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
      ++** included in the packaging of this file. Please review the following
      ++** information to ensure the GNU General Public License requirements will
      ++** be met: https://www.gnu.org/licenses/gpl-2.0.html and
      ++** https://www.gnu.org/licenses/gpl-3.0.html.
      ++**
      ++** $QT_END_LICENSE$
      ++**
      ++****************************************************************************/
      ++
      ++#include "qaccessiblequickwidget_p.h"
      ++
      ++#include "qquickwidget_p.h"
      ++
      ++QT_BEGIN_NAMESPACE
      ++
      ++#if QT_CONFIG(accessibility)
      ++
      ++QAccessibleQuickWidget::QAccessibleQuickWidget(QQuickWidget* widget)
      ++: QAccessibleWidget(widget)
      ++, m_accessibleWindow(QQuickWidgetPrivate::get(widget)->offscreenWindow)
      ++{
      ++    // NOTE: m_accessibleWindow is a QAccessibleQuickWindow, and not a
      ++    // QAccessibleQuickWidgetOffscreenWindow (defined below). This means
      ++    // it will return the Quick item child interfaces, which is what's needed here
      ++    // (unlike QAccessibleQuickWidgetOffscreenWindow, which will report 0 children).
      ++}
      ++
      ++QAccessibleInterface *QAccessibleQuickWidget::child(int index) const
      ++{
      ++    return m_accessibleWindow.child(index);
      ++}
      ++
      ++int QAccessibleQuickWidget::childCount() const
      ++{
      ++    return m_accessibleWindow.childCount();
      ++}
      ++
      ++int QAccessibleQuickWidget::indexOfChild(const QAccessibleInterface *iface) const
      ++{
      ++    return m_accessibleWindow.indexOfChild(iface);
      ++}
      ++
      ++QAccessibleInterface *QAccessibleQuickWidget::childAt(int x, int y) const
      ++{
      ++    return m_accessibleWindow.childAt(x, y);
      ++}
      ++
      ++QAccessibleQuickWidgetOffscreenWindow::QAccessibleQuickWidgetOffscreenWindow(QQuickWindow *window)
      ++:QAccessibleQuickWindow(window)
      ++{
      ++
      ++}
      ++
      ++QAccessibleInterface *QAccessibleQuickWidgetOffscreenWindow::child(int index) const
      ++{
      ++    Q_UNUSED(index);
      ++    return nullptr;
      ++}
      ++
      ++int QAccessibleQuickWidgetOffscreenWindow::childCount() const
      ++{
      ++    return 0;
      ++}
      ++
      ++int QAccessibleQuickWidgetOffscreenWindow::indexOfChild(const QAccessibleInterface *iface) const
      ++{
      ++    Q_UNUSED(iface);
      ++    return -1;
      ++}
      ++
      ++QAccessibleInterface *QAccessibleQuickWidgetOffscreenWindow::QAccessibleQuickWidgetOffscreenWindow::childAt(int x, int y) const
      ++{
      ++    Q_UNUSED(x);
      ++    Q_UNUSED(y);
      ++    return nullptr;
      ++}
      ++
      ++#endif // accessibility
      ++
      ++QT_END_NAMESPACE
      +diff --git a/qtdeclarative/src/quickwidgets/qaccessiblequickwidget_p.h b/qtdeclarative/src/quickwidgets/qaccessiblequickwidget_p.h
      +new file mode 100644
      +index 0000000000..7c2ab930e0
      +--- /dev/null
      ++++ b/qtdeclarative/src/quickwidgets/qaccessiblequickwidget_p.h
      +@@ -0,0 +1,95 @@
      ++/****************************************************************************
      ++**
      ++** Copyright (C) 2021 The Qt Company Ltd.
      ++** Contact: https://www.qt.io/licensing/
      ++**
      ++** This file is part of the QtQuick module of the Qt Toolkit.
      ++**
      ++** $QT_BEGIN_LICENSE:LGPL$
      ++** Commercial License Usage
      ++** Licensees holding valid commercial Qt licenses may use this file in
      ++** accordance with the commercial license agreement provided with the
      ++** Software or, alternatively, in accordance with the terms contained in
      ++** a written agreement between you and The Qt Company. For licensing terms
      ++** and conditions see https://www.qt.io/terms-conditions. For further
      ++** information use the contact form at https://www.qt.io/contact-us.
      ++**
      ++** GNU Lesser General Public License Usage
      ++** Alternatively, this file may be used under the terms of the GNU Lesser
      ++** General Public License version 3 as published by the Free Software
      ++** Foundation and appearing in the file LICENSE.LGPL3 included in the
      ++** packaging of this file. Please review the following information to
      ++** ensure the GNU Lesser General Public License version 3 requirements
      ++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
      ++**
      ++** GNU General Public License Usage
      ++** Alternatively, this file may be used under the terms of the GNU
      ++** General Public License version 2.0 or (at your option) the GNU General
      ++** Public license version 3 or any later version approved by the KDE Free
      ++** Qt Foundation. The licenses are as published by the Free Software
      ++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
      ++** included in the packaging of this file. Please review the following
      ++** information to ensure the GNU General Public License requirements will
      ++** be met: https://www.gnu.org/licenses/gpl-2.0.html and
      ++** https://www.gnu.org/licenses/gpl-3.0.html.
      ++**
      ++** $QT_END_LICENSE$
      ++**
      ++****************************************************************************/
      ++
      ++#ifndef QACCESSIBLEQUICKWIDGET_H
      ++#define QACCESSIBLEQUICKWIDGET_H
      ++
      ++//
      ++//  W A R N I N G
      ++//  -------------
      ++//
      ++// This file is not part of the Qt API.  It exists purely as an
      ++// implementation detail.  This header file may change from version to
      ++// version without notice, or even be removed.
      ++//
      ++// We mean it.
      ++//
      ++
      ++#include "qquickwidget.h"
      ++#include 
      ++
      ++#include 
      ++
      ++QT_BEGIN_NAMESPACE
      ++
      ++#if QT_CONFIG(accessibility)
      ++
      ++// These classes implement the QQuickWiget accessibility switcharoo,
      ++// where the child items of the QQuickWidgetOffscreenWindow are reported
      ++// as child accessible interfaces of the QAccessibleQuickWidget.
      ++class QAccessibleQuickWidget: public QAccessibleWidget
      ++{
      ++public:
      ++    QAccessibleQuickWidget(QQuickWidget* widget);
      ++
      ++    QAccessibleInterface *child(int index) const override;
      ++    int childCount() const override;
      ++    int indexOfChild(const QAccessibleInterface *iface) const override;
      ++    QAccessibleInterface *childAt(int x, int y) const override;
      ++
      ++private:
      ++    QAccessibleQuickWindow m_accessibleWindow;
      ++    Q_DISABLE_COPY(QAccessibleQuickWidget)
      ++};
      ++
      ++class QAccessibleQuickWidgetOffscreenWindow: public QAccessibleQuickWindow
      ++{
      ++public:
      ++    QAccessibleQuickWidgetOffscreenWindow(QQuickWindow *window);
      ++    QAccessibleInterface *child(int index) const override;
      ++    int childCount() const override;
      ++    int indexOfChild(const QAccessibleInterface *iface) const override;
      ++    QAccessibleInterface *childAt(int x, int y) const override;
      ++};
      ++
      ++#endif // accessibility
      ++
      ++QT_END_NAMESPACE
      ++
      ++#endif
      +diff --git a/qtdeclarative/src/quickwidgets/qaccessiblequickwidgetfactory.cpp b/qtdeclarative/src/quickwidgets/qaccessiblequickwidgetfactory.cpp
      +new file mode 100644
      +index 0000000000..7ba88a1769
      +--- /dev/null
      ++++ b/qtdeclarative/src/quickwidgets/qaccessiblequickwidgetfactory.cpp
      +@@ -0,0 +1,60 @@
      ++/****************************************************************************
      ++**
      ++** Copyright (C) 2021 The Qt Company Ltd.
      ++** Contact: https://www.qt.io/licensing/
      ++**
      ++** This file is part of the QtQuick module of the Qt Toolkit.
      ++**
      ++** $QT_BEGIN_LICENSE:LGPL$
      ++** Commercial License Usage
      ++** Licensees holding valid commercial Qt licenses may use this file in
      ++** accordance with the commercial license agreement provided with the
      ++** Software or, alternatively, in accordance with the terms contained in
      ++** a written agreement between you and The Qt Company. For licensing terms
      ++** and conditions see https://www.qt.io/terms-conditions. For further
      ++** information use the contact form at https://www.qt.io/contact-us.
      ++**
      ++** GNU Lesser General Public License Usage
      ++** Alternatively, this file may be used under the terms of the GNU Lesser
      ++** General Public License version 3 as published by the Free Software
      ++** Foundation and appearing in the file LICENSE.LGPL3 included in the
      ++** packaging of this file. Please review the following information to
      ++** ensure the GNU Lesser General Public License version 3 requirements
      ++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
      ++**
      ++** GNU General Public License Usage
      ++** Alternatively, this file may be used under the terms of the GNU
      ++** General Public License version 2.0 or (at your option) the GNU General
      ++** Public license version 3 or any later version approved by the KDE Free
      ++** Qt Foundation. The licenses are as published by the Free Software
      ++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
      ++** included in the packaging of this file. Please review the following
      ++** information to ensure the GNU General Public License requirements will
      ++** be met: https://www.gnu.org/licenses/gpl-2.0.html and
      ++** https://www.gnu.org/licenses/gpl-3.0.html.
      ++**
      ++** $QT_END_LICENSE$
      ++**
      ++****************************************************************************/
      ++
      ++#include "qaccessiblequickwidgetfactory_p.h"
      ++#include "qaccessiblequickwidget_p.h"
      ++
      ++QT_BEGIN_NAMESPACE
      ++
      ++#if QT_CONFIG(accessibility)
      ++
      ++QAccessibleInterface *qAccessibleQuickWidgetFactory(const QString &classname, QObject *object)
      ++{
      ++    if (classname == QLatin1String("QQuickWidget")) {
      ++        return new QAccessibleQuickWidget(qobject_cast(object));
      ++    } else if (classname == QLatin1String("QQuickWidgetOffscreenWindow")) {
      ++        return new QAccessibleQuickWidgetOffscreenWindow(qobject_cast(object));
      ++    }
      ++    return 0;
      ++}
      ++
      ++#endif // accessibility
      ++
      ++QT_END_NAMESPACE
      ++
      +diff --git a/qtdeclarative/src/quickwidgets/qaccessiblequickwidgetfactory_p.h b/qtdeclarative/src/quickwidgets/qaccessiblequickwidgetfactory_p.h
      +new file mode 100644
      +index 0000000000..8c63b09f81
      +--- /dev/null
      ++++ b/qtdeclarative/src/quickwidgets/qaccessiblequickwidgetfactory_p.h
      +@@ -0,0 +1,66 @@
      ++/****************************************************************************
      ++**
      ++** Copyright (C) 2021 The Qt Company Ltd.
      ++** Contact: https://www.qt.io/licensing/
      ++**
      ++** This file is part of the QtQuick module of the Qt Toolkit.
      ++**
      ++** $QT_BEGIN_LICENSE:LGPL$
      ++** Commercial License Usage
      ++** Licensees holding valid commercial Qt licenses may use this file in
      ++** accordance with the commercial license agreement provided with the
      ++** Software or, alternatively, in accordance with the terms contained in
      ++** a written agreement between you and The Qt Company. For licensing terms
      ++** and conditions see https://www.qt.io/terms-conditions. For further
      ++** information use the contact form at https://www.qt.io/contact-us.
      ++**
      ++** GNU Lesser General Public License Usage
      ++** Alternatively, this file may be used under the terms of the GNU Lesser
      ++** General Public License version 3 as published by the Free Software
      ++** Foundation and appearing in the file LICENSE.LGPL3 included in the
      ++** packaging of this file. Please review the following information to
      ++** ensure the GNU Lesser General Public License version 3 requirements
      ++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
      ++**
      ++** GNU General Public License Usage
      ++** Alternatively, this file may be used under the terms of the GNU
      ++** General Public License version 2.0 or (at your option) the GNU General
      ++** Public license version 3 or any later version approved by the KDE Free
      ++** Qt Foundation. The licenses are as published by the Free Software
      ++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
      ++** included in the packaging of this file. Please review the following
      ++** information to ensure the GNU General Public License requirements will
      ++** be met: https://www.gnu.org/licenses/gpl-2.0.html and
      ++** https://www.gnu.org/licenses/gpl-3.0.html.
      ++**
      ++** $QT_END_LICENSE$
      ++**
      ++****************************************************************************/
      ++
      ++#include 
      ++
      ++#ifndef QACCESSIBLEQUICKWIDGETFACTORY_H
      ++#define QACCESSIBLEQUICKWIDGETFACTORY_H
      ++
      ++//
      ++//  W A R N I N G
      ++//  -------------
      ++//
      ++// This file is not part of the Qt API.  It exists purely as an
      ++// implementation detail.  This header file may change from version to
      ++// version without notice, or even be removed.
      ++//
      ++// We mean it.
      ++//
      ++
      ++QT_BEGIN_NAMESPACE
      ++
      ++#if QT_CONFIG(accessibility)
      ++
      ++QAccessibleInterface *qAccessibleQuickWidgetFactory(const QString &classname, QObject *object);
      ++
      ++#endif
      ++
      ++QT_END_NAMESPACE
      ++
      ++#endif
      +diff --git a/qtdeclarative/src/quickwidgets/qquickwidget.cpp b/qtdeclarative/src/quickwidgets/qquickwidget.cpp
      +index 39780f8de3..9c97b43518 100644
      +--- a/qtdeclarative/src/quickwidgets/qquickwidget.cpp
      ++++ b/qtdeclarative/src/quickwidgets/qquickwidget.cpp
      +@@ -39,6 +39,7 @@
      + 
      + #include "qquickwidget.h"
      + #include "qquickwidget_p.h"
      ++#include "qaccessiblequickwidgetfactory_p.h"
      + 
      + #include "private/qquickwindow_p.h"
      + #include "private/qquickitem_p.h"
      +@@ -75,9 +76,16 @@
      + 
      + QT_BEGIN_NAMESPACE
      + 
      ++QQuickWidgetOffscreenWindow::QQuickWidgetOffscreenWindow(QQuickWindowPrivate &dd, QQuickRenderControl *control)
      ++:QQuickWindow(dd, control)
      ++{
      ++    setTitle(QString::fromLatin1("Offscreen"));
      ++    setObjectName(QString::fromLatin1("QQuickOffScreenWindow"));
      ++}
      ++
      + // override setVisble to prevent accidental offscreen window being created
      + // by base class.
      +-class QQuickOffcreenWindowPrivate: public QQuickWindowPrivate {
      ++class QQuickWidgetOffscreenWindowPrivate: public QQuickWindowPrivate {
      + public:
      +     void setVisible(bool visible) override {
      +         Q_Q(QWindow);
      +@@ -105,9 +113,8 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
      +     Q_Q(QQuickWidget);
      + 
      +     renderControl = new QQuickWidgetRenderControl(q);
      +-    offscreenWindow = new QQuickWindow(*new QQuickOffcreenWindowPrivate(),renderControl);
      +-    offscreenWindow->setTitle(QString::fromLatin1("Offscreen"));
      +-    offscreenWindow->setObjectName(QString::fromLatin1("QQuickOffScreenWindow"));
      ++    offscreenWindow = new QQuickWidgetOffscreenWindow(*new QQuickWidgetOffscreenWindowPrivate(), renderControl);
      ++    offscreenWindow->setScreen(q->screen());
      +     // Do not call create() on offscreenWindow.
      + 
      +     // Check if the Software Adaptation is being used
      +@@ -138,6 +145,10 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
      +     QWidget::connect(offscreenWindow, &QQuickWindow::focusObjectChanged, q, &QQuickWidget::propagateFocusObjectChanged);
      +     QObject::connect(renderControl, SIGNAL(renderRequested()), q, SLOT(triggerUpdate()));
      +     QObject::connect(renderControl, SIGNAL(sceneChanged()), q, SLOT(triggerUpdate()));
      ++
      ++#if QT_CONFIG(accessibility)
      ++    QAccessible::installFactory(&qAccessibleQuickWidgetFactory);
      ++#endif
      + }
      + 
      + void QQuickWidgetPrivate::ensureEngine() const
      +@@ -901,9 +912,7 @@ void QQuickWidgetPrivate::createContext()
      + 
      +         context = new QOpenGLContext;
      +         context->setFormat(offscreenWindow->requestedFormat());
      +-        const QWindow *win = q->window()->windowHandle();
      +-        if (win && win->screen())
      +-            context->setScreen(win->screen());
      ++        context->setScreen(q->screen());
      +         QOpenGLContext *shareContext = qt_gl_global_share_context();
      +         if (!shareContext)
      +             shareContext = QWidgetPrivate::get(q->window())->shareContext();
      +@@ -1520,19 +1529,16 @@ bool QQuickWidget::event(QEvent *e)
      +         d->handleWindowChange();
      +         break;
      + 
      +-    case QEvent::ScreenChangeInternal:
      +-        if (QWindow *window = this->window()->windowHandle()) {
      +-            QScreen *newScreen = window->screen();
      +-
      +-            if (d->offscreenWindow)
      +-                d->offscreenWindow->setScreen(newScreen);
      +-            if (d->offscreenSurface)
      +-                d->offscreenSurface->setScreen(newScreen);
      ++    case QEvent::ScreenChangeInternal: {
      ++        QScreen *newScreen = screen();
      ++        if (d->offscreenWindow)
      ++            d->offscreenWindow->setScreen(newScreen);
      ++        if (d->offscreenSurface)
      ++            d->offscreenSurface->setScreen(newScreen);
      + #if QT_CONFIG(opengl)
      +-            if (d->context)
      +-                d->context->setScreen(newScreen);
      ++        if (d->context)
      ++            d->context->setScreen(newScreen);
      + #endif
      +-        }
      + 
      +         if (d->useSoftwareRenderer
      + #if QT_CONFIG(opengl)
      +@@ -1545,7 +1551,7 @@ bool QQuickWidget::event(QEvent *e)
      +             d->render(true);
      +         }
      +         break;
      +-
      ++    }
      +     case QEvent::Show:
      +     case QEvent::Move:
      +         d->updatePosition();
      +diff --git a/qtdeclarative/src/quickwidgets/qquickwidget_p.h b/qtdeclarative/src/quickwidgets/qquickwidget_p.h
      +index 881f7f9220..1a946bcc71 100644
      +--- a/qtdeclarative/src/quickwidgets/qquickwidget_p.h
      ++++ b/qtdeclarative/src/quickwidgets/qquickwidget_p.h
      +@@ -148,6 +148,14 @@ public:
      +     bool forceFullUpdate;
      + };
      + 
      ++class QQuickWidgetOffscreenWindow: public QQuickWindow
      ++{
      ++    Q_OBJECT
      ++
      ++public:
      ++    QQuickWidgetOffscreenWindow(QQuickWindowPrivate &dd, QQuickRenderControl *control);
      ++};
      ++
      + QT_END_NAMESPACE
      + 
      + #endif // QQuickWidget_P_H
      +diff --git a/qtdeclarative/src/quickwidgets/quickwidgets.pro b/qtdeclarative/src/quickwidgets/quickwidgets.pro
      +index 2438e577ae..85d156b8a3 100644
      +--- a/qtdeclarative/src/quickwidgets/quickwidgets.pro
      ++++ b/qtdeclarative/src/quickwidgets/quickwidgets.pro
      +@@ -7,9 +7,13 @@ DEFINES   += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES QT_NO_FO
      + HEADERS += \
      +     qquickwidget.h \
      +     qquickwidget_p.h \
      +-    qtquickwidgetsglobal.h
      ++    qtquickwidgetsglobal.h \
      ++    qaccessiblequickwidget_p.h \
      ++    qaccessiblequickwidgetfactory_p.h
      + 
      + SOURCES += \
      +-    qquickwidget.cpp
      ++    qquickwidget.cpp \
      ++    qaccessiblequickwidget.cpp \
      ++    qaccessiblequickwidgetfactory.cpp
      + 
      + load(qt_module)
      +diff --git a/qtdeclarative/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/qtdeclarative/tests/auto/qml/qjsengine/tst_qjsengine.cpp
      +index 3b7d74df63..b75bf820d5 100644
      +--- a/qtdeclarative/tests/auto/qml/qjsengine/tst_qjsengine.cpp
      ++++ b/qtdeclarative/tests/auto/qml/qjsengine/tst_qjsengine.cpp
      +@@ -102,6 +102,7 @@ private slots:
      +     void valueConversion_RegularExpression();
      +     void castWithMultipleInheritance();
      +     void collectGarbage();
      ++    void collectGarbageNestedWrappersTwoEngines();
      +     void gcWithNestedDataStructure();
      +     void stacktrace();
      +     void numberParsing_data();
      +@@ -1809,6 +1810,44 @@ void tst_QJSEngine::collectGarbage()
      +     QVERIFY(ptr.isNull());
      + }
      + 
      ++class TestObjectContainer : public QObject
      ++{
      ++    Q_OBJECT
      ++    Q_PROPERTY(QObject *dummy MEMBER m_dummy CONSTANT)
      ++
      ++public:
      ++    TestObjectContainer() : m_dummy(new QObject(this)) {}
      ++
      ++private:
      ++    QObject *m_dummy;
      ++};
      ++
      ++void tst_QJSEngine::collectGarbageNestedWrappersTwoEngines()
      ++{
      ++    QJSEngine engine1;
      ++    QJSEngine engine2;
      ++
      ++    TestObjectContainer container;
      ++    QQmlEngine::setObjectOwnership(&container, QQmlEngine::CppOwnership);
      ++
      ++    engine1.globalObject().setProperty("foobar", engine1.newQObject(&container));
      ++    engine2.globalObject().setProperty("foobar", engine2.newQObject(&container));
      ++
      ++    engine1.evaluate("foobar.dummy.baz = 42");
      ++    engine2.evaluate("foobar.dummy.baz = 43");
      ++
      ++    QCOMPARE(engine1.evaluate("foobar.dummy.baz").toInt(), 42);
      ++    QCOMPARE(engine2.evaluate("foobar.dummy.baz").toInt(), 43);
      ++
      ++    engine1.collectGarbage();
      ++    engine2.collectGarbage();
      ++
      ++    // The GC should not collect dummy object wrappers neither in engine1 nor engine2, we
      ++    // verify that by checking whether the baz property still has its previous value.
      ++    QCOMPARE(engine1.evaluate("foobar.dummy.baz").toInt(), 42);
      ++    QCOMPARE(engine2.evaluate("foobar.dummy.baz").toInt(), 43);
      ++}
      ++
      + void tst_QJSEngine::gcWithNestedDataStructure()
      + {
      +     // The GC must be able to traverse deeply nested objects, otherwise this
      +diff --git a/qtdeclarative/tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml b/qtdeclarative/tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml
      +new file mode 100644
      +index 0000000000..206133bb39
      +--- /dev/null
      ++++ b/qtdeclarative/tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml
      +@@ -0,0 +1,11 @@
      ++import QtQuick 2.8
      ++
      ++ListView {
      ++    id: root
      ++    width: 200
      ++    height: 200
      ++
      ++    delegate: Text {
      ++        text: display
      ++    }
      ++}
      +diff --git a/qtdeclarative/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/qtdeclarative/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
      +index 35f1e2c94d..1722447830 100644
      +--- a/qtdeclarative/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
      ++++ b/qtdeclarative/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
      +@@ -27,6 +27,8 @@
      + ****************************************************************************/
      + 
      + #include 
      ++#include 
      ++#include 
      + #include 
      + #include 
      + #include 
      +@@ -47,6 +49,7 @@ private slots:
      +     void filterOnGroup_removeWhenCompleted();
      +     void qtbug_86017();
      +     void contextAccessedByHandler();
      ++    void redrawUponColumnChange();
      + };
      + 
      + class AbstractItemModel : public QAbstractItemModel
      +@@ -186,6 +189,30 @@ void tst_QQmlDelegateModel::contextAccessedByHandler()
      +     QVERIFY(root->property("works").toBool());
      + }
      + 
      ++void tst_QQmlDelegateModel::redrawUponColumnChange()
      ++{
      ++    QStandardItemModel m1;
      ++    m1.appendRow({
      ++            new QStandardItem("Banana"),
      ++            new QStandardItem("Coconut"),
      ++    });
      ++
      ++    QQuickView view(testFileUrl("redrawUponColumnChange.qml"));
      ++    QCOMPARE(view.status(), QQuickView::Ready);
      ++    view.show();
      ++    QQuickItem *root = view.rootObject();
      ++    root->setProperty("model", QVariant::fromValue(&m1));
      ++
      ++    QObject *item = root->property("currentItem").value();
      ++    QVERIFY(item);
      ++    QCOMPARE(item->property("text").toString(), "Banana");
      ++
      ++    QVERIFY(root);
      ++    m1.removeColumn(0);
      ++
      ++    QCOMPARE(item->property("text").toString(), "Coconut");
      ++}
      ++
      + QTEST_MAIN(tst_QQmlDelegateModel)
      + 
      + #include "tst_qqmldelegatemodel.moc"
      +diff --git a/qtdeclarative/tests/auto/qml/qv4mm/tst_qv4mm.cpp b/qtdeclarative/tests/auto/qml/qv4mm/tst_qv4mm.cpp
      +index 5d635aa63b..824fd89e5b 100644
      +--- a/qtdeclarative/tests/auto/qml/qv4mm/tst_qv4mm.cpp
      ++++ b/qtdeclarative/tests/auto/qml/qv4mm/tst_qv4mm.cpp
      +@@ -76,10 +76,10 @@ void tst_qv4mm::multiWrappedQObjects()
      +         QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 1);
      +         QCOMPARE(engine2.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0);
      + 
      +-        // Moves the additional WeakValue from m_multiplyWrappedQObjects to
      +-        // m_pendingFreedObjectWrapperValue. It's still alive after all.
      ++        // The additional WeakValue from m_multiplyWrappedQObjects hasn't been moved
      ++        // to m_pendingFreedObjectWrapperValue yet. It's still alive after all.
      +         engine1.memoryManager->runGC();
      +-        QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 2);
      ++        QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 1);
      + 
      +         // engine2 doesn't own the object as engine1 was the first to wrap it above.
      +         // Therefore, no effect here.
      +diff --git a/qtdeclarative/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop3.qml b/qtdeclarative/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop3.qml
      +new file mode 100644
      +index 0000000000..889e480f3b
      +--- /dev/null
      ++++ b/qtdeclarative/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop3.qml
      +@@ -0,0 +1,13 @@
      ++import QtQuick 2.6
      ++
      ++Item {
      ++    visible: true
      ++    Item {
      ++        visible: false
      ++        Item {
      ++            objectName: "hiddenChild"
      ++            activeFocusOnTab: true
      ++            focus: true
      ++        }
      ++    }
      ++}
      +diff --git a/qtdeclarative/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/qtdeclarative/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
      +index c8f251dbe1..c8ef36ee68 100644
      +--- a/qtdeclarative/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
      ++++ b/qtdeclarative/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
      +@@ -67,6 +67,7 @@ private slots:
      +     void activeFocusOnTab10();
      +     void activeFocusOnTab_infiniteLoop_data();
      +     void activeFocusOnTab_infiniteLoop();
      ++    void activeFocusOnTab_infiniteLoopControls();
      + 
      +     void nextItemInFocusChain();
      +     void nextItemInFocusChain2();
      +@@ -1057,6 +1058,17 @@ void tst_QQuickItem::activeFocusOnTab_infiniteLoop()
      +     QCOMPARE(item, window->rootObject());
      + }
      + 
      ++
      ++void tst_QQuickItem::activeFocusOnTab_infiniteLoopControls()
      ++{
      ++    auto source = testFileUrl("activeFocusOnTab_infiniteLoop3.qml");
      ++    QScopedPointerwindow(new QQuickView());
      ++    window->setSource(source);
      ++    window->show();
      ++    QVERIFY(window->errors().isEmpty());
      ++    QTest::keyClick(window.get(), Qt::Key_Tab); // should not hang
      ++}
      ++
      + void tst_QQuickItem::nextItemInFocusChain()
      + {
      +     if (!qt_tab_all_widgets())
      +Submodule qtdoc c0c7bf07...79d6ef69:
      +Submodule qtimageformats 2dcf2899..abe44c0f:
      +diff --git a/qtimageformats/src/plugins/imageformats/icns/qicnshandler.cpp b/qtimageformats/src/plugins/imageformats/icns/qicnshandler.cpp
      +index dde783c..1bf9074 100644
      +--- a/qtimageformats/src/plugins/imageformats/icns/qicnshandler.cpp
      ++++ b/qtimageformats/src/plugins/imageformats/icns/qicnshandler.cpp
      +@@ -462,8 +462,12 @@ static bool parseIconEntryInfo(ICNSEntry &icon)
      +     if (isIconCompressed(icon))
      +         return true;
      +     // Icon depth:
      +-    if (!depth.isEmpty())
      +-        icon.depth = ICNSEntry::Depth(depth.toUInt());
      ++    if (!depth.isEmpty()) {
      ++        const uint depthUInt = depth.toUInt();
      ++        if (depthUInt > 32)
      ++            return false;
      ++        icon.depth = ICNSEntry::Depth(depthUInt);
      ++    }
      +     // Try mono if depth not found
      +     if (icon.depth == ICNSEntry::DepthUnknown)
      +         icon.depth = ICNSEntry::DepthMono;
      +@@ -515,6 +519,9 @@ static bool parseIconEntryInfo(ICNSEntry &icon)
      +         }
      +         icon.height = icon.width;
      +     }
      ++    // Sanity check
      ++    if (icon.width == 0 || icon.width > 4096)
      ++        return false;
      +     return true;
      + }
      + 
      +@@ -685,7 +692,7 @@ bool QICNSHandler::canRead() const
      + bool QICNSHandler::read(QImage *outImage)
      + {
      +     QImage img;
      +-    if (!ensureScanned()) {
      ++    if (!ensureScanned() || m_currentIconIndex >= m_icons.size()) {
      +         qWarning("QICNSHandler::read(): The device wasn't parsed properly!");
      +         return false;
      +     }
      +@@ -892,7 +899,7 @@ bool QICNSHandler::scanDevice()
      +             return false;
      + 
      +         const qint64 blockDataOffset = device()->pos();
      +-        if (!isBlockHeaderValid(blockHeader)) {
      ++        if (!isBlockHeaderValid(blockHeader, ICNSBlockHeaderSize + filelength - blockDataOffset)) {
      +             qWarning("QICNSHandler::scanDevice(): Failed, bad header at pos %s. OSType \"%s\", length %u",
      +                      QByteArray::number(blockDataOffset).constData(),
      +                      nameFromOSType(blockHeader.ostype).constData(), blockHeader.length);
      +@@ -927,11 +934,14 @@ bool QICNSHandler::scanDevice()
      +         case ICNSBlockHeader::TypeOdrp:
      +             // Icns container seems to have an embedded icon variant container
      +             // Let's start a scan for entries
      +-            while (device()->pos() < nextBlockOffset) {
      ++            while (!stream.atEnd() && device()->pos() < nextBlockOffset) {
      +                 ICNSBlockHeader icon;
      +                 stream >> icon;
      ++                if (stream.status() != QDataStream::Ok)
      ++                    return false;
      +                 // Check for incorrect variant entry header and stop scan
      +-                if (!isBlockHeaderValid(icon, blockDataLength))
      ++                quint64 remaining = blockDataLength - (device()->pos() - blockDataOffset);
      ++                if (!isBlockHeaderValid(icon, ICNSBlockHeaderSize + remaining))
      +                     break;
      +                 if (!addEntry(icon, device()->pos(), blockHeader.ostype))
      +                     return false;
      +@@ -1003,7 +1013,7 @@ bool QICNSHandler::scanDevice()
      +             break;
      +         }
      +     }
      +-    return true;
      ++    return (m_icons.size() > 0);
      + }
      + 
      + const ICNSEntry &QICNSHandler::getIconMask(const ICNSEntry &icon) const
      +diff --git a/qtimageformats/src/plugins/imageformats/jp2/qjp2handler.cpp b/qtimageformats/src/plugins/imageformats/jp2/qjp2handler.cpp
      +index 5082023..cb34374 100644
      +--- a/qtimageformats/src/plugins/imageformats/jp2/qjp2handler.cpp
      ++++ b/qtimageformats/src/plugins/imageformats/jp2/qjp2handler.cpp
      +@@ -43,6 +43,7 @@
      + #include "qimage.h"
      + #include "qvariant.h"
      + #include "qcolor.h"
      ++#include "qimagereader.h"
      + 
      + #include 
      + #include  // for pow
      +@@ -333,16 +334,46 @@ private:
      + Jpeg2000JasperReader::Jpeg2000JasperReader(QIODevice *iod, SubFormat format)
      +     : jasperOk(true), ioDevice(iod), format(format), hasAlpha(false)
      + {
      ++#if JAS_VERSION_MAJOR < 3
      +     if (jas_init()) {
      +         jasperOk = false;
      +         qDebug("Jasper Library initialization failed");
      +     }
      ++#else
      ++    jas_conf_clear();
      ++#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
      ++    jas_conf_set_max_mem_usage(QImageReader::allocationLimit() * 1024 * 1024);
      ++#else
      ++    // 128MB seems to be enough.
      ++    jas_conf_set_max_mem_usage(128 * 1024 * 1024);
      ++#endif
      ++    if (jas_init_library()) {
      ++        jasperOk = false;
      ++        qDebug("Jasper library initialization failed");
      ++    }
      ++    if (jas_init_thread()) {
      ++        jas_cleanup_library();
      ++        jasperOk = false;
      ++        qDebug("Jasper thread initialization failed");
      ++    }
      ++#endif
      + }
      + 
      + Jpeg2000JasperReader::~Jpeg2000JasperReader()
      + {
      ++#if JAS_VERSION_MAJOR < 3
      +     if (jasperOk)
      +         jas_cleanup();
      ++#else
      ++    if (jasperOk) {
      ++        if (jas_cleanup_thread()) {
      ++            qDebug("Jasper thread cleanup failed");
      ++        }
      ++        if (jas_cleanup_library()) {
      ++            qDebug("Jasper library cleanup failed");
      ++        }
      ++    }
      ++#endif
      + }
      + 
      + /*! \internal
      +@@ -857,7 +888,7 @@ bool Jpeg2000JasperReader::write(const QImage &image, int quality)
      +     }
      + 
      +     // Open an empty jasper stream that grows automatically
      +-    jas_stream_t * memory_stream = jas_stream_memopen(0, -1);
      ++    jas_stream_t * memory_stream = jas_stream_memopen(0, 0);
      + 
      +     // Jasper wants a non-const string.
      +     char *str = qstrdup(jasperFormatString.toLatin1().constData());
      +diff --git a/qtimageformats/src/plugins/imageformats/tiff/qtiffhandler.cpp b/qtimageformats/src/plugins/imageformats/tiff/qtiffhandler.cpp
      +index 1386750..ac8956c 100644
      +--- a/qtimageformats/src/plugins/imageformats/tiff/qtiffhandler.cpp
      ++++ b/qtimageformats/src/plugins/imageformats/tiff/qtiffhandler.cpp
      +@@ -361,6 +361,8 @@ bool QTiffHandler::read(QImage *image)
      +     }
      + 
      +     TIFF *const tiff = d->tiff;
      ++    if (TIFFIsTiled(tiff) && TIFFTileSize64(tiff) > uint64_t(image->sizeInBytes())) // Corrupt image
      ++        return false;
      +     const quint32 width = d->size.width();
      +     const quint32 height = d->size.height();
      + 
      +diff --git a/qtimageformats/src/plugins/imageformats/webp/qwebphandler.cpp b/qtimageformats/src/plugins/imageformats/webp/qwebphandler.cpp
      +index 82d38cb..d02eb05 100644
      +--- a/qtimageformats/src/plugins/imageformats/webp/qwebphandler.cpp
      ++++ b/qtimageformats/src/plugins/imageformats/webp/qwebphandler.cpp
      +@@ -45,6 +45,7 @@
      + #include 
      + #include 
      + #include 
      ++#include 
      + 
      + static const int riffHeaderSize = 12; // RIFF_HEADER_SIZE from webp/format_constants.h
      + 
      +@@ -102,21 +103,23 @@ bool QWebpHandler::ensureScanned() const
      + 
      +     m_scanState = ScanError;
      + 
      +-    if (device()->isSequential()) {
      +-        qWarning() << "Sequential devices are not supported";
      ++    QWebpHandler *that = const_cast(this);
      ++    const int headerBytesNeeded = sizeof(WebPBitstreamFeatures);
      ++    QByteArray header = device()->peek(headerBytesNeeded);
      ++    if (header.size() < headerBytesNeeded)
      +         return false;
      +-    }
      + 
      +-    qint64 oldPos = device()->pos();
      +-    device()->seek(0);
      +-
      +-    QWebpHandler *that = const_cast(this);
      +-    QByteArray header = device()->peek(sizeof(WebPBitstreamFeatures));
      ++    // We do no random access during decoding, just a readAll() of the whole image file. So if
      ++    // if it is all available already, we can accept a sequential device. The riff header contains
      ++    // the file size minus 8 bytes header
      ++    qint64 byteSize = qFromLittleEndian(header.constData() + 4);
      ++    if (device()->isSequential() && device()->bytesAvailable() < byteSize + 8) {
      ++        qWarning() << "QWebpHandler: Insufficient data available in sequential device";
      ++        return false;
      ++    }
      +     if (WebPGetFeatures((const uint8_t*)header.constData(), header.size(), &(that->m_features)) == VP8_STATUS_OK) {
      +         if (m_features.has_animation) {
      +             // For animation, we have to read and scan whole file to determine loop count and images count
      +-            device()->seek(oldPos);
      +-
      +             if (that->ensureDemuxer()) {
      +                 that->m_loop = WebPDemuxGetI(m_demuxer, WEBP_FF_LOOP_COUNT);
      +                 that->m_frameCount = WebPDemuxGetI(m_demuxer, WEBP_FF_FRAME_COUNT);
      +@@ -126,17 +129,13 @@ bool QWebpHandler::ensureScanned() const
      +                 if (that->m_features.has_alpha)
      +                     that->m_composited->fill(Qt::transparent);
      + 
      +-                // We do not reset device position since we have read in all data
      +                 m_scanState = ScanSuccess;
      +-                return true;
      +             }
      +         } else {
      +             m_scanState = ScanSuccess;
      +         }
      +     }
      + 
      +-    device()->seek(oldPos);
      +-
      +     return m_scanState == ScanSuccess;
      + }
      + 
      +@@ -159,7 +158,7 @@ bool QWebpHandler::ensureDemuxer()
      + 
      + bool QWebpHandler::read(QImage *image)
      + {
      +-    if (!ensureScanned() || device()->isSequential() || !ensureDemuxer())
      ++    if (!ensureScanned() || !ensureDemuxer())
      +         return false;
      + 
      +     QRect prevFrameRect;
      +Submodule qtlocation 98a5c511..f991e28c:
      +diff --git a/qtlocation/src/location/configure.json b/qtlocation/src/location/configure.json
      +index 6d01a9a3..d1e623a1 100644
      +--- a/qtlocation/src/location/configure.json
      ++++ b/qtlocation/src/location/configure.json
      +@@ -9,7 +9,7 @@
      +             "label": "Qt.labs.location experimental QML plugin",
      +             "purpose": "Provides experimental QtLocation QML types",
      +             "section": "Location",
      +-            "condition": "config.opengl",
      ++            "condition": "features.opengl",
      +             "output": [ "privateFeature" ]
      +         },
      +         "geoservices_osm": {
      +diff --git a/qtlocation/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp b/qtlocation/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp
      +index a978573d..11e1466f 100644
      +--- a/qtlocation/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp
      ++++ b/qtlocation/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp
      +@@ -158,7 +158,7 @@ void QGeoMapObjectQSGSupport::updateMapObjects(QSGNode *root, QQuickWindow *wind
      +     if (!root)
      +         return;
      + 
      +-    if (m_mapObjectsRootNode && m_mapObjectsRootNode->parent())
      ++    if (m_mapObjectsRootNode && !m_mapObjectsRootNode->parent())
      +         root->appendChildNode(m_mapObjectsRootNode.get());
      + 
      +     if (!m_mapObjectsRootNode) {
      +diff --git a/qtlocation/src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp b/qtlocation/src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp
      +index 5a40467e..d123c6a8 100644
      +--- a/qtlocation/src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp
      ++++ b/qtlocation/src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp
      +@@ -59,8 +59,10 @@ QT_BEGIN_NAMESPACE
      + static const QString kPrefixEsri(QStringLiteral("esri."));
      + static const QString kParamUserAgent(kPrefixEsri + QStringLiteral("useragent"));
      + 
      +-static const QString kUrlGeocode(QStringLiteral("http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates"));
      +-static const QString kUrlReverseGeocode(QStringLiteral("http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode"));
      ++static const QString kUrlGeocode(QStringLiteral("https://geocode.arcgis.com/arcgis/rest/services/"
      ++                                                "World/GeocodeServer/findAddressCandidates"));
      ++static const QString kUrlReverseGeocode(QStringLiteral(
      ++        "https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode"));
      + 
      + static QString addressToQuery(const QGeoAddress &address)
      + {
      +diff --git a/qtlocation/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp b/qtlocation/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp
      +index 17492d94..96c12b1b 100644
      +--- a/qtlocation/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp
      ++++ b/qtlocation/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp
      +@@ -46,7 +46,8 @@
      + 
      + QT_BEGIN_NAMESPACE
      + 
      +-// JSON reference: http://resources.arcgis.com/en/help/arcgis-rest-api/#/Route_service_with_synchronous_execution/02r300000036000000/
      ++// JSON reference:
      ++// https://resources.arcgis.com/en/help/arcgis-rest-api/#/Route_service_with_synchronous_execution/02r300000036000000/
      + 
      + static const QString kErrorMessage(QStringLiteral("Error %1: %2."));
      + static const QString kErrorJson(QStringLiteral("Error: invalide JSON document."));
      +diff --git a/qtlocation/src/plugins/geoservices/esri/georoutereply_esri.cpp b/qtlocation/src/plugins/geoservices/esri/georoutereply_esri.cpp
      +index 8cadfb29..92b6bb13 100644
      +--- a/qtlocation/src/plugins/geoservices/esri/georoutereply_esri.cpp
      ++++ b/qtlocation/src/plugins/geoservices/esri/georoutereply_esri.cpp
      +@@ -44,7 +44,8 @@
      + 
      + QT_BEGIN_NAMESPACE
      + 
      +-// JSON reference: http://resources.arcgis.com/en/help/arcgis-rest-api/#/Route_service_with_synchronous_execution/02r300000036000000/
      ++// JSON reference:
      ++// https://resources.arcgis.com/en/help/arcgis-rest-api/#/Route_service_with_synchronous_execution/02r300000036000000/
      + 
      + GeoRouteReplyEsri::GeoRouteReplyEsri(QNetworkReply *reply, const QGeoRouteRequest &request,
      +                                      QObject *parent) :
      +diff --git a/qtlocation/src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp b/qtlocation/src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp
      +index 0e6bc2c7..ed613f4b 100644
      +--- a/qtlocation/src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp
      ++++ b/qtlocation/src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp
      +@@ -48,7 +48,8 @@ static const QString kPrefixEsri(QStringLiteral("esri."));
      + static const QString kParamUserAgent(kPrefixEsri + QStringLiteral("useragent"));
      + static const QString kParamToken(kPrefixEsri + QStringLiteral("token"));
      + 
      +-static const QString kUrlRouting(QStringLiteral("http://route.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World/solve"));
      ++static const QString kUrlRouting(QStringLiteral(
      ++        "https://route.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World/solve"));
      + 
      + GeoRoutingManagerEngineEsri::GeoRoutingManagerEngineEsri(const QVariantMap ¶meters,
      +                                                          QGeoServiceProvider::Error *error,
      +@@ -70,7 +71,8 @@ GeoRoutingManagerEngineEsri::~GeoRoutingManagerEngineEsri()
      + {
      + }
      + 
      +-// REST reference: http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#//02r300000036000000
      ++// REST reference:
      ++// https://resources.arcgis.com/en/help/arcgis-rest-api/index.html#//02r300000036000000
      + 
      + QGeoRouteReply *GeoRoutingManagerEngineEsri::calculateRoute(const QGeoRouteRequest &request)
      + {
      +@@ -125,7 +127,7 @@ void GeoRoutingManagerEngineEsri::replyError(QGeoRouteReply::Error errorCode, co
      + QString GeoRoutingManagerEngineEsri::preferedDirectionLangage()
      + {
      +     // list of supported langages is defined in:
      +-    // http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#//02r300000036000000
      ++    // https://resources.arcgis.com/en/help/arcgis-rest-api/index.html#//02r300000036000000
      +     const QStringList supportedLanguages = {
      +         "ar", // Generate directions in Arabic
      +         "cs", // Generate directions in Czech
      +diff --git a/qtlocation/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp b/qtlocation/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp
      +index 5d15835d..24148f95 100644
      +--- a/qtlocation/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp
      ++++ b/qtlocation/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp
      +@@ -230,7 +230,8 @@ QGeoMap *GeoTiledMappingManagerEngineEsri::createMap()
      + // ${y} = Y
      + // ${token} = Token
      + 
      +-// template = 'http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{{z}}/{{y}}/{{x}}.png'
      ++// template =
      ++// 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{{z}}/{{y}}/{{x}}.png'
      + 
      + bool GeoTiledMappingManagerEngineEsri::initializeMapSources(QGeoServiceProvider::Error *error,
      +                                                             QString *errorString,
      +diff --git a/qtlocation/src/plugins/geoservices/esri/maps.json b/qtlocation/src/plugins/geoservices/esri/maps.json
      +index 8167ae7d..862e087d 100644
      +--- a/qtlocation/src/plugins/geoservices/esri/maps.json
      ++++ b/qtlocation/src/plugins/geoservices/esri/maps.json
      +@@ -6,8 +6,8 @@
      +             "description": "ArcGIS Online World Street Map",
      +             "mobile": true,
      +             "night": false,
      +-            "url": "http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer",
      +-            "copyrightText": "© Esri contributors"
      ++            "url": "https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer",
      ++            "copyrightText": "© Esri contributors"
      +         },
      + 
      +         {
      +@@ -16,8 +16,8 @@
      +             "": "ArcGIS Online World Imagery",
      +             "mobile": true,
      +             "night": false,
      +-            "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
      +-            "copyrightText": "© Esri contributors"
      ++            "url": "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
      ++            "copyrightText": "© Esri contributors"
      +         },
      + 
      +         {
      +@@ -26,8 +26,8 @@
      +             "description": "ArcGIS Online World Terrain Base",
      +             "mobile": false,
      +             "night": false,
      +-            "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Terrain_Base/MapServer",
      +-            "copyrightText": "© Esri contributors"
      ++            "url": "https://server.arcgisonline.com/ArcGIS/rest/services/World_Terrain_Base/MapServer",
      ++            "copyrightText": "© Esri contributors"
      +         },
      + 
      +         {
      +@@ -36,8 +36,8 @@
      +             "description": "ArcGIS Online World Topography",
      +             "mobile": true,
      +             "night": false,
      +-            "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer",
      +-            "copyrightText": "© Esri contributors"
      ++            "url": "https://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer",
      ++            "copyrightText": "© Esri contributors"
      +         },
      + 
      +         {
      +@@ -46,8 +46,8 @@
      +             "description": "This map presents land cover and detailed topographic maps for the United States.",
      +             "mobile": true,
      +             "night": false,
      +-            "url": "http://services.arcgisonline.com/ArcGIS/rest/services/USA_Topo_Maps/MapServer",
      +-            "copyrightText": "© Esri contributors"
      ++            "url": "https://services.arcgisonline.com/ArcGIS/rest/services/USA_Topo_Maps/MapServer",
      ++            "copyrightText": "© Esri contributors"
      +         },
      + 
      +         {
      +@@ -56,8 +56,8 @@
      +             "description": "National Geographic World Map",
      +             "mobile": false,
      +             "night": false,
      +-            "url": "http://services.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer",
      +-            "copyrightText": "© Esri contributors"
      ++            "url": "https://services.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer",
      ++            "copyrightText": "© Esri contributors"
      +         },
      + 
      +         {
      +@@ -66,8 +66,8 @@
      +             "description": "Thematic content providing a neutral background with minimal colors",
      +             "mobile": true,
      +             "night": false,
      +-            "url": "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer",
      +-            "copyrightText": "© Esri contributors"
      ++            "url": "https://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer",
      ++            "copyrightText": "© Esri contributors"
      +         },
      + 
      +         {
      +@@ -76,8 +76,8 @@
      +             "description": "Natural Earth physical map for the world",
      +             "mobile": false,
      +             "night": false,
      +-            "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Physical_Map/MapServer",
      +-            "copyrightText": "© Esri contributors"
      ++            "url": "https://server.arcgisonline.com/ArcGIS/rest/services/World_Physical_Map/MapServer",
      ++            "copyrightText": "© Esri contributors"
      +         },
      + 
      +         {
      +@@ -86,8 +86,8 @@
      +             "description": "Portrays surface elevation as shaded relief",
      +             "mobile": false,
      +             "night": false,
      +-            "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer",
      +-            "copyrightText": "© Esri contributors"
      ++            "url": "https://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer",
      ++            "copyrightText": "© Esri contributors"
      +         },
      + 
      +         {
      +@@ -96,8 +96,8 @@
      +             "description": "This map is designed to be used as a basemap by marine GIS professionals and as a reference map by anyone interested in ocean data",
      +             "mobile": false,
      +             "night": false,
      +-            "url": "http://server.arcgisonline.com/arcgis/rest/services/Ocean/World_Ocean_Base/MapServer",
      +-            "copyrightText": "© Esri contributors"
      ++            "url": "https://server.arcgisonline.com/arcgis/rest/services/Ocean/World_Ocean_Base/MapServer",
      ++            "copyrightText": "© Esri contributors"
      +         },
      + 
      +         {
      +@@ -106,8 +106,8 @@
      +             "description": "Thematic content providing a neutral background with minimal colors",
      +             "mobile": false,
      +             "night": true,
      +-            "url": "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Dark_Gray_Base/MapServer",
      +-            "copyrightText": "© Esri contributors"
      ++            "url": "https://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Dark_Gray_Base/MapServer",
      ++            "copyrightText": "© Esri contributors"
      +         },
      + 
      +         {
      +@@ -116,8 +116,8 @@
      +             "description": "DeLorme’s topographic basemap is a seamless global data set that portrays transportation, hydrography, jurisdiction boundaries, and major geographic features",
      +             "mobile": false,
      +             "night": false,
      +-            "url": "http://server.arcgisonline.com/ArcGIS/rest/services/Specialty/DeLorme_World_Base_Map/MapServer",
      +-            "copyrightText": "© Esri contributors"
      ++            "url": "https://server.arcgisonline.com/ArcGIS/rest/services/Specialty/DeLorme_World_Base_Map/MapServer",
      ++            "copyrightText": "© Esri contributors"
      +         }
      +     ]
      + }
      +diff --git a/qtlocation/src/plugins/geoservices/esri/placemanagerengine_esri.cpp b/qtlocation/src/plugins/geoservices/esri/placemanagerengine_esri.cpp
      +index 3858ddf5..af66f28e 100644
      +--- a/qtlocation/src/plugins/geoservices/esri/placemanagerengine_esri.cpp
      ++++ b/qtlocation/src/plugins/geoservices/esri/placemanagerengine_esri.cpp
      +@@ -63,8 +63,10 @@ static const QString kCountriesKey(QStringLiteral("detailedCountries"));
      + static const QString kLocalizedNamesKey(QStringLiteral("localizedNames"));
      + static const QString kMaxLocationsKey(QStringLiteral("maxLocations"));
      + 
      +-static const QUrl kUrlGeocodeServer("http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer?f=pjson");
      +-static const QUrl kUrlFindAddressCandidates("http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates");
      ++static const QUrl kUrlGeocodeServer(
      ++        "https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer?f=pjson");
      ++static const QUrl kUrlFindAddressCandidates("https://geocode.arcgis.com/arcgis/rest/services/World/"
      ++                                            "GeocodeServer/findAddressCandidates");
      + 
      + PlaceManagerEngineEsri::PlaceManagerEngineEsri(const QVariantMap ¶meters, QGeoServiceProvider::Error *error,
      +                                                QString *errorString) :
      +Submodule qtmultimedia f0344079..0d7cc33a:
      +diff --git a/qtmultimedia/src/plugins/pulseaudio/qaudioinput_pulse.cpp b/qtmultimedia/src/plugins/pulseaudio/qaudioinput_pulse.cpp
      +index 2b5325132..b68b4af1b 100644
      +--- a/qtmultimedia/src/plugins/pulseaudio/qaudioinput_pulse.cpp
      ++++ b/qtmultimedia/src/plugins/pulseaudio/qaudioinput_pulse.cpp
      +@@ -402,6 +402,8 @@ int QPulseAudioInput::bytesReady() const
      + 
      + qint64 QPulseAudioInput::read(char *data, qint64 len)
      + {
      ++    Q_ASSERT(data != nullptr || len == 0);
      ++
      +     m_bytesAvailable = checkBytesReady();
      + 
      +     setError(QAudio::NoError);
      +@@ -411,7 +413,8 @@ qint64 QPulseAudioInput::read(char *data, qint64 len)
      + 
      +     if (!m_pullMode && !m_tempBuffer.isEmpty()) {
      +         readBytes = qMin(static_cast(len), m_tempBuffer.size());
      +-        memcpy(data, m_tempBuffer.constData(), readBytes);
      ++        if (readBytes)
      ++            memcpy(data, m_tempBuffer.constData(), readBytes);
      +         m_totalTimeValue += readBytes;
      + 
      +         if (readBytes < m_tempBuffer.size()) {
      +@@ -502,9 +505,10 @@ qint64 QPulseAudioInput::read(char *data, qint64 len)
      + 
      + void QPulseAudioInput::applyVolume(const void *src, void *dest, int len)
      + {
      ++    Q_ASSERT((src && dest) || len == 0);
      +     if (m_volume < 1.f)
      +         QAudioHelperInternal::qMultiplySamples(m_volume, m_format, src, dest, len);
      +-    else
      ++    else if (len)
      +         memcpy(dest, src, len);
      + }
      + 
      +Submodule qtpim 02efef5e...f9a8f0fc (commits not present)
      +Submodule qtquick3d b85cf622..47defc8b:
      +diff --git a/qtquick3d/src/plugins/assetimporters/assimp/assimp.pro b/qtquick3d/src/plugins/assetimporters/assimp/assimp.pro
      +index ca5c499e..174a075b 100644
      +--- a/qtquick3d/src/plugins/assetimporters/assimp/assimp.pro
      ++++ b/qtquick3d/src/plugins/assetimporters/assimp/assimp.pro
      +@@ -10,7 +10,7 @@ QT_FOR_CONFIG += assetimporters-private
      + include($$OUT_PWD/../qtassetimporters-config.pri)
      + 
      + qtConfig(system-assimp):!if(cross_compile:host_build) {
      +-    QMAKE_USE_PRIVATE += assimp
      ++    QMAKE_USE_PRIVATE += quick3d-assimp
      + } else {
      +     include(../../../3rdparty/assimp/assimp.pri)
      + }
      +Submodule qtquickcontrols2 3a657dc0..56ce8233:
      +diff --git a/qtquickcontrols2/src/imports/platform/widgets/qwidgetplatformmenu.cpp b/qtquickcontrols2/src/imports/platform/widgets/qwidgetplatformmenu.cpp
      +index e5fe734f7..e36922775 100644
      +--- a/qtquickcontrols2/src/imports/platform/widgets/qwidgetplatformmenu.cpp
      ++++ b/qtquickcontrols2/src/imports/platform/widgets/qwidgetplatformmenu.cpp
      +@@ -38,6 +38,7 @@
      + #include "qwidgetplatformmenuitem_p.h"
      + 
      + #include 
      ++#include 
      + #include 
      + #include 
      + 
      +@@ -145,7 +146,7 @@ void QWidgetPlatformMenu::showPopup(const QWindow *window, const QRect &targetRe
      + 
      +     QPoint targetPos = targetRect.bottomLeft();
      +     if (window)
      +-        targetPos = window->mapToGlobal(targetPos);
      ++        targetPos = window->mapToGlobal(QHighDpi::fromNativeLocalPosition(targetPos, window));
      + 
      +     const QWidgetPlatformMenuItem *widgetItem = qobject_cast(item);
      +     m_menu->popup(targetPos, widgetItem ? widgetItem->action() : nullptr);
      +diff --git a/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton.cpp b/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton.cpp
      +index 950e4e099..b81fbea0b 100644
      +--- a/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton.cpp
      ++++ b/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton.cpp
      +@@ -387,6 +387,17 @@ void QQuickAbstractButtonPrivate::itemImplicitHeightChanged(QQuickItem *item)
      +         emit q->implicitIndicatorHeightChanged();
      + }
      + 
      ++void QQuickAbstractButtonPrivate::itemDestroyed(QQuickItem *item)
      ++{
      ++    Q_Q(QQuickAbstractButton);
      ++    QQuickControlPrivate::itemDestroyed(item);
      ++    if (item == indicator) {
      ++        indicator = nullptr;
      ++        emit q->implicitIndicatorWidthChanged();
      ++        emit q->implicitIndicatorHeightChanged();
      ++    }
      ++}
      ++
      + QQuickAbstractButton *QQuickAbstractButtonPrivate::findCheckedButton() const
      + {
      +     Q_Q(const QQuickAbstractButton);
      +@@ -1176,6 +1187,12 @@ QAccessible::Role QQuickAbstractButton::accessibleRole() const
      +     }
      +     return QAccessible::Button;
      + }
      ++
      ++void QQuickAbstractButton::accessiblePressAction()
      ++{
      ++    Q_D(QQuickAbstractButton);
      ++    d->trigger();
      ++}
      + #endif
      + 
      + QT_END_NAMESPACE
      +diff --git a/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton_p.h b/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton_p.h
      +index 0fa48980e..ab66220d0 100644
      +--- a/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton_p.h
      ++++ b/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton_p.h
      +@@ -209,6 +209,7 @@ protected:
      + #if QT_CONFIG(accessibility)
      +     void accessibilityActiveChanged(bool active) override;
      +     QAccessible::Role accessibleRole() const override;
      ++    Q_INVOKABLE void accessiblePressAction();
      + #endif
      + 
      + private:
      +diff --git a/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton_p_p.h b/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton_p_p.h
      +index 9291c1a87..b729720f2 100644
      +--- a/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton_p_p.h
      ++++ b/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton_p_p.h
      +@@ -109,6 +109,7 @@ public:
      + 
      +     void itemImplicitWidthChanged(QQuickItem *item) override;
      +     void itemImplicitHeightChanged(QQuickItem *item) override;
      ++    void itemDestroyed(QQuickItem *item) override;
      + 
      +     // copied from qabstractbutton.cpp
      +     static const int AUTO_REPEAT_DELAY = 300;
      +diff --git a/qtquickcontrols2/src/quicktemplates2/qquickaction.cpp b/qtquickcontrols2/src/quicktemplates2/qquickaction.cpp
      +index 2041e7741..8610cdfae 100644
      +--- a/qtquickcontrols2/src/quicktemplates2/qquickaction.cpp
      ++++ b/qtquickcontrols2/src/quicktemplates2/qquickaction.cpp
      +@@ -145,7 +145,7 @@ int QQuickActionPrivate::ShortcutEntry::shortcutId() const
      + 
      + void QQuickActionPrivate::ShortcutEntry::grab(const QKeySequence &shortcut, bool enabled)
      + {
      +-    if (shortcut.isEmpty())
      ++    if (shortcut.isEmpty() || m_shortcutId)
      +         return;
      + 
      +     Qt::ShortcutContext context = Qt::WindowShortcut; // TODO
      +diff --git a/qtquickcontrols2/src/quicktemplates2/qquickcontainer.cpp b/qtquickcontrols2/src/quicktemplates2/qquickcontainer.cpp
      +index f38c2b09c..6eed2a024 100644
      +--- a/qtquickcontrols2/src/quicktemplates2/qquickcontainer.cpp
      ++++ b/qtquickcontrols2/src/quicktemplates2/qquickcontainer.cpp
      +@@ -225,6 +225,7 @@ void QQuickContainerPrivate::cleanup()
      +     QObject::disconnect(contentModel, &QQmlObjectModel::countChanged, q, &QQuickContainer::countChanged);
      +     QObject::disconnect(contentModel, &QQmlObjectModel::childrenChanged, q, &QQuickContainer::contentChildrenChanged);
      +     delete contentModel;
      ++    contentModel = nullptr;
      + }
      + 
      + QQuickItem *QQuickContainerPrivate::itemAt(int index) const
      +@@ -436,7 +437,7 @@ void QQuickContainerPrivate::contentChildren_clear(QQmlListProperty
      + void QQuickContainerPrivate::updateContentWidth()
      + {
      +     Q_Q(QQuickContainer);
      +-    if (hasContentWidth || qFuzzyCompare(contentWidth, implicitContentWidth))
      ++    if (hasContentWidth || qFuzzyCompare(contentWidth, implicitContentWidth) || !contentModel)
      +         return;
      + 
      +     contentWidth = implicitContentWidth;
      +@@ -446,7 +447,7 @@ void QQuickContainerPrivate::updateContentWidth()
      + void QQuickContainerPrivate::updateContentHeight()
      + {
      +     Q_Q(QQuickContainer);
      +-    if (hasContentHeight || qFuzzyCompare(contentHeight, implicitContentHeight))
      ++    if (hasContentHeight || qFuzzyCompare(contentHeight, implicitContentHeight) || !contentModel)
      +         return;
      + 
      +     contentHeight = implicitContentHeight;
      +diff --git a/qtquickcontrols2/src/quicktemplates2/qquickcontrol.cpp b/qtquickcontrols2/src/quicktemplates2/qquickcontrol.cpp
      +index bbbd0e622..1f4b47343 100644
      +--- a/qtquickcontrols2/src/quicktemplates2/qquickcontrol.cpp
      ++++ b/qtquickcontrols2/src/quicktemplates2/qquickcontrol.cpp
      +@@ -845,6 +845,13 @@ void QQuickControlPrivate::executeBackground(bool complete)
      +         quickCompleteDeferred(q, backgroundName(), background);
      + }
      + 
      ++/*
      ++    \internal
      ++
      ++    Hides an item that was replaced by a newer one, rather than
      ++    deleting it, as the item is typically created in QML and hence
      ++    we don't own it.
      ++*/
      + void QQuickControlPrivate::hideOldItem(QQuickItem *item)
      + {
      +     if (!item)
      +@@ -863,6 +870,29 @@ void QQuickControlPrivate::hideOldItem(QQuickItem *item)
      + #endif
      + }
      + 
      ++/*
      ++    \internal
      ++
      ++    Named "unhide" because it's used for cases where an item
      ++    that was previously hidden by \l hideOldItem() wants to be
      ++    shown by a control again, such as a ScrollBar in ScrollView.
      ++*/
      ++void QQuickControlPrivate::unhideOldItem(QQuickControl *control, QQuickItem *item)
      ++{
      ++    Q_ASSERT(item);
      ++    qCDebug(lcItemManagement) << "unhiding old item" << item;
      ++
      ++    item->setVisible(true);
      ++    item->setParentItem(control);
      ++
      ++#if QT_CONFIG(accessibility)
      ++    // Add the item back in to the accessibility tree.
      ++    QQuickAccessibleAttached *accessible = accessibleAttached(item);
      ++    if (accessible)
      ++        accessible->setIgnored(false);
      ++#endif
      ++}
      ++
      + void QQuickControlPrivate::updateBaselineOffset()
      + {
      +     Q_Q(QQuickControl);
      +diff --git a/qtquickcontrols2/src/quicktemplates2/qquickcontrol_p_p.h b/qtquickcontrols2/src/quicktemplates2/qquickcontrol_p_p.h
      +index 8e979079e..a6e624c91 100644
      +--- a/qtquickcontrols2/src/quicktemplates2/qquickcontrol_p_p.h
      ++++ b/qtquickcontrols2/src/quicktemplates2/qquickcontrol_p_p.h
      +@@ -173,6 +173,7 @@ public:
      +     virtual void executeBackground(bool complete = false);
      + 
      +     static void hideOldItem(QQuickItem *item);
      ++    static void unhideOldItem(QQuickControl *control, QQuickItem *item);
      + 
      +     void updateBaselineOffset();
      + 
      +diff --git a/qtquickcontrols2/src/quicktemplates2/qquickdialogbuttonbox.cpp b/qtquickcontrols2/src/quicktemplates2/qquickdialogbuttonbox.cpp
      +index e6db14eb5..6197d1547 100644
      +--- a/qtquickcontrols2/src/quicktemplates2/qquickdialogbuttonbox.cpp
      ++++ b/qtquickcontrols2/src/quicktemplates2/qquickdialogbuttonbox.cpp
      +@@ -237,7 +237,7 @@ static QRectF alignedRect(Qt::LayoutDirection direction, Qt::Alignment alignment
      + void QQuickDialogButtonBoxPrivate::resizeContent()
      + {
      +     Q_Q(QQuickDialogButtonBox);
      +-    if (!contentItem)
      ++    if (!contentItem || !contentModel)
      +         return;
      + 
      +     QRectF geometry = q->boundingRect().adjusted(q->leftPadding(), q->topPadding(), -q->rightPadding(), -q->bottomPadding());
      +@@ -322,6 +322,9 @@ void QQuickDialogButtonBoxPrivate::updateLayout()
      + qreal QQuickDialogButtonBoxPrivate::getContentWidth() const
      + {
      +     Q_Q(const QQuickDialogButtonBox);
      ++    if (!contentModel)
      ++        return 0;
      ++
      +     const int count = contentModel->count();
      +     const qreal totalSpacing = qMax(0, count - 1) * spacing;
      +     qreal totalWidth = totalSpacing;
      +@@ -341,6 +344,9 @@ qreal QQuickDialogButtonBoxPrivate::getContentWidth() const
      + qreal QQuickDialogButtonBoxPrivate::getContentHeight() const
      + {
      +     Q_Q(const QQuickDialogButtonBox);
      ++    if (!contentModel)
      ++        return 0;
      ++
      +     const int count = contentModel->count();
      +     qreal maxHeight = 0;
      +     for (int i = 0; i < count; ++i) {
      +diff --git a/qtquickcontrols2/src/quicktemplates2/qquickoverlay.cpp b/qtquickcontrols2/src/quicktemplates2/qquickoverlay.cpp
      +index 91bd59184..0ce518f84 100644
      +--- a/qtquickcontrols2/src/quicktemplates2/qquickoverlay.cpp
      ++++ b/qtquickcontrols2/src/quicktemplates2/qquickoverlay.cpp
      +@@ -399,8 +399,11 @@ void QQuickOverlay::itemChange(ItemChange change, const ItemChangeData &data)
      +     Q_D(QQuickOverlay);
      +     QQuickItem::itemChange(change, data);
      + 
      +-    if (change == ItemChildAddedChange || change == ItemChildRemovedChange)
      ++    if (change == ItemChildAddedChange || change == ItemChildRemovedChange) {
      +         setVisible(!d->allDrawers.isEmpty() || !childItems().isEmpty());
      ++        if (data.item->parent() == d->mouseGrabberPopup)
      ++            d->setMouseGrabberPopup(nullptr);
      ++    }
      + }
      + 
      + void QQuickOverlay::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
      +diff --git a/qtquickcontrols2/src/quicktemplates2/qquickscrollbar.cpp b/qtquickcontrols2/src/quicktemplates2/qquickscrollbar.cpp
      +index 4e2f509db..1c4b308cd 100644
      +--- a/qtquickcontrols2/src/quicktemplates2/qquickscrollbar.cpp
      ++++ b/qtquickcontrols2/src/quicktemplates2/qquickscrollbar.cpp
      +@@ -797,6 +797,14 @@ void QQuickScrollBarAttachedPrivate::initHorizontal()
      +     if (parent && parent == flickable->parentItem())
      +         horizontal->stackAfter(flickable);
      + 
      ++    // If a scroll bar was previously hidden (due to e.g. setting a new contentItem
      ++    // on a ScrollView), we need to make sure that we un-hide it.
      ++    // We don't bother checking if the item is actually the old one, because
      ++    // if it's not, all of the things the function does (setting parent, visibility, etc.)
      ++    // should be no-ops anyway.
      ++    if (auto control = qobject_cast(q_ptr->parent()))
      ++        QQuickControlPrivate::unhideOldItem(control, horizontal);
      ++
      +     layoutHorizontal();
      +     horizontal->setSize(area->property("widthRatio").toReal());
      +     horizontal->setPosition(area->property("xPosition").toReal());
      +@@ -818,6 +826,9 @@ void QQuickScrollBarAttachedPrivate::initVertical()
      +     if (parent && parent == flickable->parentItem())
      +         vertical->stackAfter(flickable);
      + 
      ++    if (auto control = qobject_cast(q_ptr->parent()))
      ++        QQuickControlPrivate::unhideOldItem(control, vertical);
      ++
      +     layoutVertical();
      +     vertical->setSize(area->property("heightRatio").toReal());
      +     vertical->setPosition(area->property("yPosition").toReal());
      +diff --git a/qtquickcontrols2/tests/auto/controls/data/tst_scrollview.qml b/qtquickcontrols2/tests/auto/controls/data/tst_scrollview.qml
      +index 0e8b08352..cd4931184 100644
      +--- a/qtquickcontrols2/tests/auto/controls/data/tst_scrollview.qml
      ++++ b/qtquickcontrols2/tests/auto/controls/data/tst_scrollview.qml
      +@@ -576,4 +576,51 @@ TestCase {
      +         verify(newHorizontalScrollBar.visible)
      +         verify(!oldHorizontalScrollBar.visible)
      +     }
      ++
      ++    Component {
      ++        id: bindingToContentItemAndStandaloneFlickable
      ++
      ++        Item {
      ++            width: 200
      ++            height: 200
      ++
      ++            property alias scrollView: scrollView
      ++
      ++            ScrollView {
      ++                id: scrollView
      ++                anchors.fill: parent
      ++                contentItem: listView
      ++
      ++                property Item someBinding: contentItem
      ++            }
      ++            ListView {
      ++                id: listView
      ++                model: 10
      ++                delegate: ItemDelegate {
      ++                    text: modelData
      ++                    width: listView.width
      ++                }
      ++            }
      ++        }
      ++    }
      ++
      ++    // Tests that scroll bars show up for a ScrollView where
      ++    // - its contentItem is declared as a standalone, separate item
      ++    // - there is a binding to contentItem (which causes a default Flickable to be created)
      ++    function test_bindingToContentItemAndStandaloneFlickable() {
      ++        let root = createTemporaryObject(bindingToContentItemAndStandaloneFlickable, testCase)
      ++        verify(root)
      ++
      ++        let control = root.scrollView
      ++        let verticalScrollBar = control.ScrollBar.vertical
      ++        let horizontalScrollBar = control.ScrollBar.horizontal
      ++        compare(verticalScrollBar.parent, control)
      ++        compare(horizontalScrollBar.parent, control)
      ++        verify(verticalScrollBar.visible)
      ++        verify(horizontalScrollBar.visible)
      ++
      ++        mouseDrag(verticalScrollBar, verticalScrollBar.width / 2, verticalScrollBar.height / 2, 0, 50)
      ++        verify(verticalScrollBar.active)
      ++        verify(horizontalScrollBar.active)
      ++    }
      + }
      +diff --git a/qtquickcontrols2/tests/auto/controls/data/tst_switch.qml b/qtquickcontrols2/tests/auto/controls/data/tst_switch.qml
      +index b3fab41ca..10b6baa02 100644
      +--- a/qtquickcontrols2/tests/auto/controls/data/tst_switch.qml
      ++++ b/qtquickcontrols2/tests/auto/controls/data/tst_switch.qml
      +@@ -608,4 +608,27 @@ TestCase {
      +         mouseClick(control.indicator)
      +         verify(control.activeFocus)
      +     }
      ++
      ++    Component {
      ++        id: deletionOrder1
      ++        Item {
      ++            Image { id: innerImage }
      ++            Switch { indicator: innerImage }
      ++        }
      ++    }
      ++
      ++    Component {
      ++        id: deletionOrder2
      ++        Item {
      ++            Switch { indicator: innerImage }
      ++            Image { id: innerImage }
      ++        }
      ++    }
      ++
      ++    function test_deletionOrder() {
      ++        var control1 = createTemporaryObject(deletionOrder1, testCase)
      ++        verify(control1)
      ++        var control2 = createTemporaryObject(deletionOrder2, testCase)
      ++        verify(control2)
      ++    }
      + }
      +diff --git a/qtquickcontrols2/tests/auto/qquickpopup/data/releaseAfterExitTransition.qml b/qtquickcontrols2/tests/auto/qquickpopup/data/releaseAfterExitTransition.qml
      +new file mode 100644
      +index 000000000..9e4598b9f
      +--- /dev/null
      ++++ b/qtquickcontrols2/tests/auto/qquickpopup/data/releaseAfterExitTransition.qml
      +@@ -0,0 +1,78 @@
      ++/****************************************************************************
      ++**
      ++** Copyright (C) 2021 The Qt Company Ltd.
      ++** Contact: https://www.qt.io/licensing/
      ++**
      ++** This file is part of the test suite of the Qt Toolkit.
      ++**
      ++** $QT_BEGIN_LICENSE:BSD$
      ++** Commercial License Usage
      ++** Licensees holding valid commercial Qt licenses may use this file in
      ++** accordance with the commercial license agreement provided with the
      ++** Software or, alternatively, in accordance with the terms contained in
      ++** a written agreement between you and The Qt Company. For licensing terms
      ++** and conditions see https://www.qt.io/terms-conditions. For further
      ++** information use the contact form at https://www.qt.io/contact-us.
      ++**
      ++** BSD License Usage
      ++** Alternatively, you may use this file under the terms of the BSD license
      ++** as follows:
      ++**
      ++** "Redistribution and use in source and binary forms, with or without
      ++** modification, are permitted provided that the following conditions are
      ++** met:
      ++**   * Redistributions of source code must retain the above copyright
      ++**     notice, this list of conditions and the following disclaimer.
      ++**   * Redistributions in binary form must reproduce the above copyright
      ++**     notice, this list of conditions and the following disclaimer in
      ++**     the documentation and/or other materials provided with the
      ++**     distribution.
      ++**   * Neither the name of The Qt Company Ltd nor the names of its
      ++**     contributors may be used to endorse or promote products derived
      ++**     from this software without specific prior written permission.
      ++**
      ++**
      ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
      ++**
      ++** $QT_END_LICENSE$
      ++**
      ++****************************************************************************/
      ++
      ++import QtQuick 2.15
      ++import QtQuick.Controls 2.15
      ++
      ++ApplicationWindow {
      ++    id: window
      ++    width: 400
      ++    height: 400
      ++    title: "releaseAfterExitTransition"
      ++
      ++    property alias popup: popup
      ++    property alias modalPopup: modalPopup
      ++
      ++    Popup {
      ++        id: popup
      ++        y: parent.height - height
      ++        width: 50
      ++        height: 50
      ++    }
      ++
      ++    Popup {
      ++        id: modalPopup
      ++        modal: true
      ++        y: parent.height - height
      ++        width: 50
      ++        height: 50
      ++        exit:  Transition { PauseAnimation { duration: 100 } }
      ++    }
      ++}
      +diff --git a/qtquickcontrols2/tests/auto/qquickpopup/tst_qquickpopup.cpp b/qtquickcontrols2/tests/auto/qquickpopup/tst_qquickpopup.cpp
      +index 54952d128..3d50e2dd4 100644
      +--- a/qtquickcontrols2/tests/auto/qquickpopup/tst_qquickpopup.cpp
      ++++ b/qtquickcontrols2/tests/auto/qquickpopup/tst_qquickpopup.cpp
      +@@ -100,6 +100,7 @@ private slots:
      +     void invisibleToolTipOpen();
      +     void centerInOverlayWithinStackViewItem();
      +     void destroyDuringExitTransition();
      ++    void releaseAfterExitTransition();
      + };
      + 
      + void tst_QQuickPopup::initTestCase()
      +@@ -1575,6 +1576,34 @@ void tst_QQuickPopup::destroyDuringExitTransition()
      +     QVERIFY(!button->isDown());
      + }
      + 
      ++void tst_QQuickPopup::releaseAfterExitTransition()
      ++{
      ++    QQuickApplicationHelper helper(this, "releaseAfterExitTransition.qml");
      ++    QVERIFY2(helper.ready, helper.failureMessage());
      ++
      ++    QQuickWindow *window = helper.window;
      ++    window->show();
      ++    QVERIFY(QTest::qWaitForWindowActive(window));
      ++
      ++    QQuickOverlay *overlay = QQuickOverlay::overlay(window);
      ++    QQuickPopup *modalPopup = window->property("modalPopup").value();
      ++    QQuickPopup *popup = window->property("popup").value();
      ++
      ++    modalPopup->open();
      ++    QTRY_VERIFY(modalPopup->isOpened());
      ++
      ++    QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1));
      ++    // wait until the transition is finished and the overlay hides itself
      ++    QTRY_VERIFY(!overlay->isVisible());
      ++    QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1));
      ++
      ++    popup->open();
      ++    QTRY_VERIFY(popup->isOpened());
      ++    QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1));
      ++    QTRY_VERIFY(!popup->isOpened());
      ++}
      ++
      ++
      + QTEST_QUICKCONTROLS_MAIN(tst_QQuickPopup)
      + 
      + #include "tst_qquickpopup.moc"
      +Submodule qtscript 5be95f96...4d8e4bd2 (commits not present)
      +Submodule qtspeech 17fc9fde..255845e2:
      +diff --git a/qtspeech/src/plugins/tts/speechdispatcher/qtexttospeech_speechd.cpp b/qtspeech/src/plugins/tts/speechdispatcher/qtexttospeech_speechd.cpp
      +index 6eb74b8..bcc7dd1 100644
      +--- a/qtspeech/src/plugins/tts/speechdispatcher/qtexttospeech_speechd.cpp
      ++++ b/qtspeech/src/plugins/tts/speechdispatcher/qtexttospeech_speechd.cpp
      +@@ -357,7 +357,9 @@ QVector QTextToSpeechEngineSpeechd::availableLocales() const
      + 
      + QVector QTextToSpeechEngineSpeechd::availableVoices() const
      + {
      +-    return m_voices.values(m_currentLocale.name()).toVector();
      ++    QList resultList = m_voices.values(m_currentLocale.name());
      ++    std::reverse(resultList.begin(), resultList.end());
      ++    return resultList.toVector();
      + }
      + 
      + // We have no way of knowing our own client_id since speech-dispatcher seems to be incomplete
      +Submodule qtsvg 0c05780e..a7a0f249:
      +diff --git a/qtsvg/src/plugins/imageformats/svg/qsvgiohandler.cpp b/qtsvg/src/plugins/imageformats/svg/qsvgiohandler.cpp
      +index 561e77e..12e0574 100644
      +--- a/qtsvg/src/plugins/imageformats/svg/qsvgiohandler.cpp
      ++++ b/qtsvg/src/plugins/imageformats/svg/qsvgiohandler.cpp
      +@@ -191,6 +191,8 @@ bool QSvgIOHandler::read(QImage *image)
      +             }
      +         }
      +         if (!finalSize.isEmpty()) {
      ++            if (qMax(finalSize.width(), finalSize.height()) > 0xffff)
      ++                return false; // Assume corrupted file
      +             image->fill(d->backColor.rgba());
      +             QPainter p(image);
      +             d->r.render(&p, bounds);
      +diff --git a/qtsvg/src/svg/qsvghandler.cpp b/qtsvg/src/svg/qsvghandler.cpp
      +index a5f877f..8dda563 100644
      +--- a/qtsvg/src/svg/qsvghandler.cpp
      ++++ b/qtsvg/src/svg/qsvghandler.cpp
      +@@ -1393,9 +1393,10 @@ static void parseFont(QSvgNode *node,
      +         case FontSizeNone:
      +             break;
      +         case FontSizeValue: {
      +-            QSvgHandler::LengthType dummy; // should always be pixel size
      +-            fontStyle->setSize(qMin(parseLength(attributes.fontSize, dummy, handler),
      +-                                    qreal(0xffff)));
      ++            QSvgHandler::LengthType type;
      ++            qreal fs = parseLength(attributes.fontSize, type, handler);
      ++            fs = convertToPixels(fs, true, type);
      ++            fontStyle->setSize(qMin(fs, qreal(0xffff)));
      +         }
      +             break;
      +         default:
      +@@ -2513,6 +2514,8 @@ static bool parseAnimateTransformNode(QSvgNode *parent,
      +             ++s;
      +         }
      +     }
      ++    if (vals.count() % 3 != 0)
      ++        return false;
      + 
      +     bool ok = true;
      +     int begin = parseClockValue(beginStr, &ok);
      +@@ -2576,6 +2579,8 @@ static QSvgNode *createCircleNode(QSvgNode *parent,
      +     qreal ncx = toDouble(cx);
      +     qreal ncy = toDouble(cy);
      +     qreal nr  = toDouble(r);
      ++    if (nr < 0.0)
      ++        return nullptr;
      + 
      +     QRectF rect(ncx-nr, ncy-nr, nr*2, nr*2);
      +     QSvgNode *circle = new QSvgCircle(parent, rect);
      +@@ -3046,15 +3051,16 @@ static QSvgStyleProperty *createRadialGradientNode(QSvgNode *node,
      + 
      +     qreal ncx = 0.5;
      +     qreal ncy = 0.5;
      +-    qreal nr  = 0.5;
      +     if (!cx.isEmpty())
      +         ncx = toDouble(cx);
      +     if (!cy.isEmpty())
      +         ncy = toDouble(cy);
      ++
      ++    qreal nr = 0.0;
      +     if (!r.isEmpty())
      +         nr = toDouble(r);
      +-    if (nr < 0.5)
      +-        nr = 0.5;
      ++    if (nr <= 0.0)
      ++        return nullptr;
      + 
      +     qreal nfx = ncx;
      +     if (!fx.isEmpty())
      +@@ -3350,7 +3356,9 @@ static QSvgNode *createTextNode(QSvgNode *parent,
      +     //### editable and rotate not handled
      +     QSvgHandler::LengthType type;
      +     qreal nx = parseLength(x, type, handler);
      ++    nx = convertToPixels(nx, true, type);
      +     qreal ny = parseLength(y, type, handler);
      ++    ny = convertToPixels(ny, true, type);
      + 
      +     QSvgNode *text = new QSvgText(parent, QPointF(nx, ny));
      +     return text;
      +@@ -3691,9 +3699,7 @@ void QSvgHandler::parse()
      +         case QXmlStreamReader::EndElement:
      +             endElement(xml->name());
      +             ++remainingUnfinishedElements;
      +-            // if we are using somebody else's qxmlstreamreader
      +-            // we should not read until the end of the stream
      +-            done = !m_ownsReader && (xml->name() == QLatin1String("svg"));
      ++            done = (xml->name() == QLatin1String("svg"));
      +             break;
      +         case QXmlStreamReader::Characters:
      +             characters(xml->text());
      +diff --git a/qtsvg/src/svg/qsvgstructure.cpp b/qtsvg/src/svg/qsvgstructure.cpp
      +index b89608b..89c9e4e 100644
      +--- a/qtsvg/src/svg/qsvgstructure.cpp
      ++++ b/qtsvg/src/svg/qsvgstructure.cpp
      +@@ -255,9 +255,13 @@ inline static bool isSupportedSvgFeature(const QString &str)
      +     };
      + 
      +     if (str.length() <= MAX_WORD_LENGTH && str.length() >= MIN_WORD_LENGTH) {
      ++        const char16_t unicode44 = str.at(44).unicode();
      ++        const char16_t unicode45 = str.at(45).unicode();
      ++        if (unicode44 >= sizeof(asso_values) || unicode45 >= sizeof(asso_values))
      ++            return false;
      +         const int key = str.length()
      +-                        + asso_values[str.at(45).unicode()]
      +-                        + asso_values[str.at(44).unicode()];
      ++                        + asso_values[unicode45]
      ++                        + asso_values[unicode44];
      +         if (key <= MAX_HASH_VALUE && key >= 0)
      +             return str == QLatin1String(wordlist[key]);
      +     }
      +diff --git a/qtsvg/src/svg/qsvgtinydocument.cpp b/qtsvg/src/svg/qsvgtinydocument.cpp
      +index 63d0797..19e7154 100644
      +--- a/qtsvg/src/svg/qsvgtinydocument.cpp
      ++++ b/qtsvg/src/svg/qsvgtinydocument.cpp
      +@@ -433,8 +433,16 @@ void QSvgTinyDocument::draw(QPainter *p, QSvgExtraStates &)
      +     draw(p);
      + }
      + 
      ++static bool isValidMatrix(const QTransform &transform)
      ++{
      ++    qreal determinant = transform.determinant();
      ++    return qIsFinite(determinant);
      ++}
      ++
      + void QSvgTinyDocument::mapSourceToTarget(QPainter *p, const QRectF &targetRect, const QRectF &sourceRect)
      + {
      ++    QTransform oldTransform = p->worldTransform();
      ++
      +     QRectF target = targetRect;
      +     if (target.isEmpty()) {
      +         QPaintDevice *dev = p->device();
      +@@ -487,6 +495,9 @@ void QSvgTinyDocument::mapSourceToTarget(QPainter *p, const QRectF &targetRect,
      +         }
      + #endif
      +     }
      ++
      ++    if (!isValidMatrix(p->worldTransform()))
      ++        p->setWorldTransform(oldTransform);
      + }
      + 
      + QRectF QSvgTinyDocument::boundsOnElement(const QString &id) const
      +diff --git a/qtsvg/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/qtsvg/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
      +index 36c76ec..db71e02 100644
      +--- a/qtsvg/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
      ++++ b/qtsvg/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
      +@@ -86,6 +86,8 @@ private slots:
      +     void oss_fuzz_23731();
      +     void oss_fuzz_24131();
      +     void oss_fuzz_24738();
      ++    void illegalAnimateTransform_data();
      ++    void illegalAnimateTransform();
      + 
      + #ifndef QT_NO_COMPRESS
      +     void testGzLoading();
      +@@ -1646,5 +1648,22 @@ void tst_QSvgRenderer::oss_fuzz_24738()
      +     QSvgRenderer().load(QByteArray(""));
      + }
      + 
      ++void tst_QSvgRenderer::illegalAnimateTransform_data()
      ++{
      ++    QTest::addColumn("svg");
      ++
      ++    QTest::newRow("case1") << QByteArray("");
      ++    QTest::newRow("case2") << QByteArray("");
      ++    QTest::newRow("case3") << QByteArray("");
      ++    QTest::newRow("case4") << QByteArray("");
      ++}
      ++
      ++void tst_QSvgRenderer::illegalAnimateTransform()
      ++{
      ++    QFETCH(QByteArray, svg);
      ++    QSvgRenderer renderer;
      ++    QVERIFY(!renderer.load(svg)); // also shouldn't assert
      ++}
      ++
      + QTEST_MAIN(tst_QSvgRenderer)
      + #include "tst_qsvgrenderer.moc"
      +Submodule qttools 6914f7c8..090e526e:
      +diff --git a/qttools/src/assistant/qhelpgenerator/helpgenerator.cpp b/qttools/src/assistant/qhelpgenerator/helpgenerator.cpp
      +index feab1e2d5..cbfb82507 100644
      +--- a/qttools/src/assistant/qhelpgenerator/helpgenerator.cpp
      ++++ b/qttools/src/assistant/qhelpgenerator/helpgenerator.cpp
      +@@ -445,7 +445,9 @@ bool HelpGeneratorPrivate::insertFiles(const QStringList &files, const QString &
      +     if (filterSetId < 0)
      +         return false;
      +     ++filterSetId;
      +-    for (int attId : qAsConst(filterAtts)) {
      ++    QList attValues = filterAtts.values();
      ++    std::sort(attValues.begin(), attValues.end());
      ++    for (int attId : qAsConst(attValues)) {
      +         m_query->prepare(QLatin1String("INSERT INTO FileAttributeSetTable "
      +             "VALUES(?, ?)"));
      +         m_query->bindValue(0, filterSetId);
      +Submodule qtwayland dfb0129c..2904e1b3:
      +diff --git a/qtwayland/src/client/configure.json b/qtwayland/src/client/configure.json
      +index 2f424580..29222357 100644
      +--- a/qtwayland/src/client/configure.json
      ++++ b/qtwayland/src/client/configure.json
      +@@ -149,8 +149,7 @@
      +                     "#endif"
      +                 ]
      +             },
      +-            "libs": "-ldrm",
      +-            "use": "egl"
      ++            "use": "drm egl"
      +         },
      +         "vulkan-server-buffer": {
      +             "label": "Vulkan Buffer Sharing",
      +@@ -168,7 +167,8 @@
      +                     "exportAllocInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;",
      +                     "return 0;"
      +                 ]
      +-            }
      ++            },
      ++            "use": "wayland-client"
      +         },
      +         "egl_1_5-wayland": {
      +             "label": "EGL 1.5 with Wayland Platform",
      +@@ -183,7 +183,7 @@
      +                     "eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_EXT, (struct wl_display *)(nullptr), nullptr);"
      +                 ]
      +             },
      +-            "use": "egl"
      ++            "use": "egl wayland-client"
      +         }
      +     },
      + 
      +diff --git a/qtwayland/src/client/global/qwaylandclientextension.cpp b/qtwayland/src/client/global/qwaylandclientextension.cpp
      +index 125b1e19..edccfe63 100644
      +--- a/qtwayland/src/client/global/qwaylandclientextension.cpp
      ++++ b/qtwayland/src/client/global/qwaylandclientextension.cpp
      +@@ -74,7 +74,10 @@ void QWaylandClientExtensionPrivate::handleRegistryGlobal(void *data, ::wl_regis
      + void QWaylandClientExtension::addRegistryListener()
      + {
      +     Q_D(QWaylandClientExtension);
      +-    d->waylandIntegration->display()->addRegistryListener(&QWaylandClientExtensionPrivate::handleRegistryGlobal, this);
      ++    if (!d->registered) {
      ++        d->waylandIntegration->display()->addRegistryListener(&QWaylandClientExtensionPrivate::handleRegistryGlobal, this);
      ++        d->registered = true;
      ++    }
      + }
      + 
      + QWaylandClientExtension::QWaylandClientExtension(const int ver)
      +@@ -88,6 +91,13 @@ QWaylandClientExtension::QWaylandClientExtension(const int ver)
      +     QMetaObject::invokeMethod(this, "addRegistryListener", Qt::QueuedConnection);
      + }
      + 
      ++QWaylandClientExtension::~QWaylandClientExtension()
      ++{
      ++    Q_D(QWaylandClientExtension);
      ++    if (d->registered && !QCoreApplication::closingDown())
      ++        d->waylandIntegration->display()->removeListener(&QWaylandClientExtensionPrivate::handleRegistryGlobal, this);
      ++}
      ++
      + QtWaylandClient::QWaylandIntegration *QWaylandClientExtension::integration() const
      + {
      +     Q_D(const QWaylandClientExtension);
      +diff --git a/qtwayland/src/client/global/qwaylandclientextension.h b/qtwayland/src/client/global/qwaylandclientextension.h
      +index 98272e57..5bd28398 100644
      +--- a/qtwayland/src/client/global/qwaylandclientextension.h
      ++++ b/qtwayland/src/client/global/qwaylandclientextension.h
      +@@ -63,6 +63,7 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandClientExtension : public QObject
      +     Q_PROPERTY(bool active READ isActive NOTIFY activeChanged)
      + public:
      +     QWaylandClientExtension(const int version);
      ++    ~QWaylandClientExtension();
      + 
      +     QtWaylandClient::QWaylandIntegration *integration() const;
      +     int version() const;
      +diff --git a/qtwayland/src/client/global/qwaylandclientextension_p.h b/qtwayland/src/client/global/qwaylandclientextension_p.h
      +index 69cc46a0..9091efbe 100644
      +--- a/qtwayland/src/client/global/qwaylandclientextension_p.h
      ++++ b/qtwayland/src/client/global/qwaylandclientextension_p.h
      +@@ -68,6 +68,7 @@ public:
      +     QtWaylandClient::QWaylandIntegration *waylandIntegration = nullptr;
      +     int version = -1;
      +     bool active = false;
      ++    bool registered = false;
      + };
      + 
      + class Q_WAYLAND_CLIENT_EXPORT QWaylandClientExtensionTemplatePrivate : public QWaylandClientExtensionPrivate
      +diff --git a/qtwayland/src/client/qwaylanddatadevice.cpp b/qtwayland/src/client/qwaylanddatadevice.cpp
      +index 7e2e3308..e3e60ed5 100644
      +--- a/qtwayland/src/client/qwaylanddatadevice.cpp
      ++++ b/qtwayland/src/client/qwaylanddatadevice.cpp
      +@@ -72,6 +72,8 @@ QWaylandDataDevice::QWaylandDataDevice(QWaylandDataDeviceManager *manager, QWayl
      + 
      + QWaylandDataDevice::~QWaylandDataDevice()
      + {
      ++    if (wl_data_device_get_version(object()) >= WL_DATA_DEVICE_RELEASE_SINCE_VERSION)
      ++        release();
      + }
      + 
      + QWaylandDataOffer *QWaylandDataDevice::selectionOffer() const
      +@@ -110,7 +112,7 @@ QWaylandDataOffer *QWaylandDataDevice::dragOffer() const
      +     return m_dragOffer.data();
      + }
      + 
      +-bool QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
      ++bool QWaylandDataDevice::startDrag(QMimeData *mimeData, Qt::DropActions supportedActions, QWaylandWindow *icon)
      + {
      +     auto *seat = m_display->currentInputDevice();
      +     auto *origin = seat->pointerFocus();
      +@@ -123,7 +125,28 @@ bool QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
      +     }
      + 
      +     m_dragSource.reset(new QWaylandDataSource(m_display->dndSelectionHandler(), mimeData));
      ++
      ++    if (wl_data_device_get_version(object()) >= 3)
      ++        m_dragSource->set_actions(dropActionsToWl(supportedActions));
      ++
      +     connect(m_dragSource.data(), &QWaylandDataSource::cancelled, this, &QWaylandDataDevice::dragSourceCancelled);
      ++    connect(m_dragSource.data(), &QWaylandDataSource::dndResponseUpdated, this, [this](bool accepted, Qt::DropAction action) {
      ++            auto drag = static_cast(QGuiApplicationPrivate::platformIntegration()->drag());
      ++            // in old versions drop action is not set, so we guess
      ++            if (wl_data_source_get_version(m_dragSource->object()) < 3) {
      ++                drag->setResponse(accepted);
      ++            } else {
      ++                QPlatformDropQtResponse response(accepted, action);
      ++                drag->setResponse(response);
      ++            }
      ++    });
      ++    connect(m_dragSource.data(), &QWaylandDataSource::dndDropped, this, [](bool accepted, Qt::DropAction action) {
      ++        QPlatformDropQtResponse response(accepted, action);
      ++        static_cast(QGuiApplicationPrivate::platformIntegration()->drag())->setDropResponse(response);
      ++    });
      ++    connect(m_dragSource.data(), &QWaylandDataSource::finished, this, []() {
      ++        static_cast(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag();
      ++    });
      + 
      +     start_drag(m_dragSource->object(), origin->wlSurface(), icon->wlSurface(), m_display->currentInputDevice()->serial());
      +     return true;
      +@@ -152,7 +175,7 @@ void QWaylandDataDevice::data_device_drop()
      +         supportedActions = drag->supportedActions();
      +     } else if (m_dragOffer) {
      +         dragData = m_dragOffer->mimeData();
      +-        supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
      ++        supportedActions = m_dragOffer->supportedActions();
      +     } else {
      +         return;
      +     }
      +@@ -162,7 +185,11 @@ void QWaylandDataDevice::data_device_drop()
      +                                                                           QGuiApplication::keyboardModifiers());
      + 
      +     if (drag) {
      +-        static_cast(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag(response);
      ++        auto drag =  static_cast(QGuiApplicationPrivate::platformIntegration()->drag());
      ++        drag->setDropResponse(response);
      ++        drag->finishDrag();
      ++    } else if (m_dragOffer) {
      ++        m_dragOffer->finish();
      +     }
      + }
      + 
      +@@ -186,7 +213,7 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface,
      +         supportedActions = drag->supportedActions();
      +     } else if (m_dragOffer) {
      +         dragData = m_dragOffer->mimeData();
      +-        supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
      ++        supportedActions = m_dragOffer->supportedActions();
      +     }
      + 
      +     const QPlatformDragQtResponse &response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions,
      +@@ -197,11 +224,7 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface,
      +         static_cast(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
      +     }
      + 
      +-    if (response.isAccepted()) {
      +-        wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, m_dragOffer->firstFormat().toUtf8().constData());
      +-    } else {
      +-        wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, nullptr);
      +-    }
      ++    sendResponse(supportedActions, response);
      + }
      + 
      + void QWaylandDataDevice::data_device_leave()
      +@@ -235,10 +258,10 @@ void QWaylandDataDevice::data_device_motion(uint32_t time, wl_fixed_t x, wl_fixe
      +         supportedActions = drag->supportedActions();
      +     } else {
      +         dragData = m_dragOffer->mimeData();
      +-        supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
      ++        supportedActions = m_dragOffer->supportedActions();
      +     }
      + 
      +-    QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions,
      ++    const QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions,
      +                                                                           QGuiApplication::mouseButtons(),
      +                                                                           QGuiApplication::keyboardModifiers());
      + 
      +@@ -246,11 +269,7 @@ void QWaylandDataDevice::data_device_motion(uint32_t time, wl_fixed_t x, wl_fixe
      +         static_cast(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
      +     }
      + 
      +-    if (response.isAccepted()) {
      +-        wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, m_dragOffer->firstFormat().toUtf8().constData());
      +-    } else {
      +-        wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, nullptr);
      +-    }
      ++    sendResponse(supportedActions, response);
      + }
      + #endif // QT_CONFIG(draganddrop)
      + 
      +@@ -277,14 +296,10 @@ void QWaylandDataDevice::selectionSourceCancelled()
      + #if QT_CONFIG(draganddrop)
      + void QWaylandDataDevice::dragSourceCancelled()
      + {
      ++    static_cast(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag();
      +     m_dragSource.reset();
      + }
      + 
      +-void QWaylandDataDevice::dragSourceTargetChanged(const QString &mimeType)
      +-{
      +-    static_cast(QGuiApplicationPrivate::platformIntegration()->drag())->updateTarget(mimeType);
      +-}
      +-
      + QPoint QWaylandDataDevice::calculateDragPosition(int x, int y, QWindow *wnd) const
      + {
      +     QPoint pnt(wl_fixed_to_int(x), wl_fixed_to_int(y));
      +@@ -297,6 +312,33 @@ QPoint QWaylandDataDevice::calculateDragPosition(int x, int y, QWindow *wnd) con
      +     }
      +     return pnt;
      + }
      ++
      ++void QWaylandDataDevice::sendResponse(Qt::DropActions supportedActions, const QPlatformDragQtResponse &response)
      ++{
      ++    if (response.isAccepted()) {
      ++        if (wl_data_device_get_version(object()) >= 3)
      ++            m_dragOffer->set_actions(dropActionsToWl(supportedActions), dropActionsToWl(response.acceptedAction()));
      ++
      ++        m_dragOffer->accept(m_enterSerial, m_dragOffer->firstFormat());
      ++    } else {
      ++        m_dragOffer->accept(m_enterSerial, QString());
      ++    }
      ++}
      ++
      ++int QWaylandDataDevice::dropActionsToWl(Qt::DropActions actions)
      ++{
      ++
      ++    int wlActions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
      ++    if (actions & Qt::CopyAction)
      ++        wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
      ++    if (actions & (Qt::MoveAction | Qt::TargetMoveAction))
      ++        wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
      ++
      ++    // wayland does not support LinkAction at the time of writing
      ++    return wlActions;
      ++}
      ++
      ++
      + #endif // QT_CONFIG(draganddrop)
      + 
      + }
      +diff --git a/qtwayland/src/client/qwaylanddatadevice_p.h b/qtwayland/src/client/qwaylanddatadevice_p.h
      +index 16c3ad28..801dcc2c 100644
      +--- a/qtwayland/src/client/qwaylanddatadevice_p.h
      ++++ b/qtwayland/src/client/qwaylanddatadevice_p.h
      +@@ -64,6 +64,7 @@ QT_REQUIRE_CONFIG(wayland_datadevice);
      + QT_BEGIN_NAMESPACE
      + 
      + class QMimeData;
      ++class QPlatformDragQtResponse;
      + class QWindow;
      + 
      + namespace QtWaylandClient {
      +@@ -89,7 +90,7 @@ public:
      + 
      + #if QT_CONFIG(draganddrop)
      +     QWaylandDataOffer *dragOffer() const;
      +-    bool startDrag(QMimeData *mimeData, QWaylandWindow *icon);
      ++    bool startDrag(QMimeData *mimeData, Qt::DropActions supportedActions, QWaylandWindow *icon);
      +     void cancelDrag();
      + #endif
      + 
      +@@ -109,13 +110,16 @@ private Q_SLOTS:
      + 
      + #if QT_CONFIG(draganddrop)
      +     void dragSourceCancelled();
      +-    void dragSourceTargetChanged(const QString &mimeType);
      + #endif
      + 
      + private:
      + #if QT_CONFIG(draganddrop)
      +     QPoint calculateDragPosition(int x, int y, QWindow *wnd) const;
      + #endif
      ++    void sendResponse(Qt::DropActions supportedActions, const QPlatformDragQtResponse &response);
      ++
      ++    static int dropActionsToWl(Qt::DropActions dropActions);
      ++
      + 
      +     QWaylandDisplay *m_display = nullptr;
      +     QWaylandInputDevice *m_inputDevice = nullptr;
      +diff --git a/qtwayland/src/client/qwaylanddatadevicemanager.cpp b/qtwayland/src/client/qwaylanddatadevicemanager.cpp
      +index 35d67307..6dc4f77f 100644
      +--- a/qtwayland/src/client/qwaylanddatadevicemanager.cpp
      ++++ b/qtwayland/src/client/qwaylanddatadevicemanager.cpp
      +@@ -50,8 +50,8 @@ QT_BEGIN_NAMESPACE
      + 
      + namespace QtWaylandClient {
      + 
      +-QWaylandDataDeviceManager::QWaylandDataDeviceManager(QWaylandDisplay *display, uint32_t id)
      +-    : wl_data_device_manager(display->wl_registry(), id, 1)
      ++QWaylandDataDeviceManager::QWaylandDataDeviceManager(QWaylandDisplay *display, int version, uint32_t id)
      ++    : wl_data_device_manager(display->wl_registry(), id, qMin(version, 3))
      +     , m_display(display)
      + {
      +     // Create transfer devices for all input devices.
      +diff --git a/qtwayland/src/client/qwaylanddatadevicemanager_p.h b/qtwayland/src/client/qwaylanddatadevicemanager_p.h
      +index bd05c0fb..510d9be4 100644
      +--- a/qtwayland/src/client/qwaylanddatadevicemanager_p.h
      ++++ b/qtwayland/src/client/qwaylanddatadevicemanager_p.h
      +@@ -68,7 +68,7 @@ class QWaylandInputDevice;
      + class Q_WAYLAND_CLIENT_EXPORT QWaylandDataDeviceManager : public QtWayland::wl_data_device_manager
      + {
      + public:
      +-    QWaylandDataDeviceManager(QWaylandDisplay *display, uint32_t id);
      ++    QWaylandDataDeviceManager(QWaylandDisplay *display, int version, uint32_t id);
      +     ~QWaylandDataDeviceManager() override;
      + 
      +     QWaylandDataDevice *getDataDevice(QWaylandInputDevice *inputDevice);
      +diff --git a/qtwayland/src/client/qwaylanddataoffer.cpp b/qtwayland/src/client/qwaylanddataoffer.cpp
      +index 2297e8a1..fe0ea8c9 100644
      +--- a/qtwayland/src/client/qwaylanddataoffer.cpp
      ++++ b/qtwayland/src/client/qwaylanddataoffer.cpp
      +@@ -82,6 +82,15 @@ QMimeData *QWaylandDataOffer::mimeData()
      +     return m_mimeData.data();
      + }
      + 
      ++Qt::DropActions QWaylandDataOffer::supportedActions() const
      ++{
      ++    if (wl_data_offer_get_version(const_cast<::wl_data_offer*>(object())) < 3) {
      ++        return Qt::MoveAction | Qt::CopyAction;
      ++    }
      ++
      ++    return m_supportedActions;
      ++}
      ++
      + void QWaylandDataOffer::startReceiving(const QString &mimeType, int fd)
      + {
      +     receive(mimeType, fd);
      +@@ -93,6 +102,22 @@ void QWaylandDataOffer::data_offer_offer(const QString &mime_type)
      +     m_mimeData->appendFormat(mime_type);
      + }
      + 
      ++void QWaylandDataOffer::data_offer_action(uint32_t dnd_action)
      ++{
      ++    Q_UNUSED(dnd_action);
      ++    // This is the compositor telling the drag target what action it should perform
      ++    // It does not map nicely into Qt final drop semantics, other than pretending there is only one supported action?
      ++}
      ++
      ++void QWaylandDataOffer::data_offer_source_actions(uint32_t source_actions)
      ++{
      ++    m_supportedActions = Qt::DropActions();
      ++    if (source_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
      ++        m_supportedActions |= Qt::MoveAction;
      ++    if (source_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
      ++        m_supportedActions |= Qt::CopyAction;
      ++}
      ++
      + QWaylandMimeData::QWaylandMimeData(QWaylandAbstractDataOffer *dataOffer)
      +     : m_dataOffer(dataOffer)
      + {
      +@@ -163,17 +188,18 @@ QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::T
      + 
      + int QWaylandMimeData::readData(int fd, QByteArray &data) const
      + {
      +-    fd_set readset;
      +-    FD_ZERO(&readset);
      +-    FD_SET(fd, &readset);
      +-    struct timeval timeout;
      ++    struct pollfd readset;
      ++    readset.fd = fd;
      ++    readset.events = POLLIN;
      ++    struct timespec timeout;
      +     timeout.tv_sec = 1;
      +-    timeout.tv_usec = 0;
      ++    timeout.tv_nsec = 0;
      ++
      + 
      +     Q_FOREVER {
      +-        int ready = select(FD_SETSIZE, &readset, nullptr, nullptr, &timeout);
      ++        int ready = qt_safe_poll(&readset, 1, &timeout);
      +         if (ready < 0) {
      +-            qWarning() << "QWaylandDataOffer: select() failed";
      ++            qWarning() << "QWaylandDataOffer: qt_safe_poll() failed";
      +             return -1;
      +         } else if (ready == 0) {
      +             qWarning("QWaylandDataOffer: timeout reading from pipe");
      +diff --git a/qtwayland/src/client/qwaylanddataoffer_p.h b/qtwayland/src/client/qwaylanddataoffer_p.h
      +index 9cf1483c..6f667398 100644
      +--- a/qtwayland/src/client/qwaylanddataoffer_p.h
      ++++ b/qtwayland/src/client/qwaylanddataoffer_p.h
      +@@ -82,6 +82,7 @@ public:
      +     explicit QWaylandDataOffer(QWaylandDisplay *display, struct ::wl_data_offer *offer);
      +     ~QWaylandDataOffer() override;
      +     QMimeData *mimeData() override;
      ++    Qt::DropActions supportedActions() const;
      + 
      +     QString firstFormat() const;
      + 
      +@@ -89,10 +90,13 @@ public:
      + 
      + protected:
      +     void data_offer_offer(const QString &mime_type) override;
      ++    void data_offer_source_actions(uint32_t source_actions) override;
      ++    void data_offer_action(uint32_t dnd_action) override;
      + 
      + private:
      +     QWaylandDisplay *m_display = nullptr;
      +     QScopedPointer m_mimeData;
      ++    Qt::DropActions m_supportedActions;
      + };
      + 
      + 
      +diff --git a/qtwayland/src/client/qwaylanddatasource.cpp b/qtwayland/src/client/qwaylanddatasource.cpp
      +index f45122fb..5599cbd4 100644
      +--- a/qtwayland/src/client/qwaylanddatasource.cpp
      ++++ b/qtwayland/src/client/qwaylanddatasource.cpp
      +@@ -101,7 +101,32 @@ void QWaylandDataSource::data_source_send(const QString &mime_type, int32_t fd)
      + 
      + void QWaylandDataSource::data_source_target(const QString &mime_type)
      + {
      +-    Q_EMIT targetChanged(mime_type);
      ++    m_accepted = !mime_type.isEmpty();
      ++    Q_EMIT dndResponseUpdated(m_accepted, m_dropAction);
      ++}
      ++
      ++void QWaylandDataSource::data_source_action(uint32_t action)
      ++{
      ++    Qt::DropAction qtAction = Qt::IgnoreAction;
      ++
      ++    if (action == WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
      ++        qtAction = Qt::MoveAction;
      ++    else if (action == WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
      ++        qtAction = Qt::CopyAction;
      ++
      ++    m_dropAction = qtAction;
      ++    Q_EMIT dndResponseUpdated(m_accepted, m_dropAction);
      ++}
      ++
      ++void QWaylandDataSource::data_source_dnd_finished()
      ++{
      ++    Q_EMIT finished();
      ++}
      ++
      ++void QWaylandDataSource::data_source_dnd_drop_performed()
      ++{
      ++
      ++    Q_EMIT dndDropped(m_accepted, m_dropAction);
      + }
      + 
      + }
      +diff --git a/qtwayland/src/client/qwaylanddatasource_p.h b/qtwayland/src/client/qwaylanddatasource_p.h
      +index 25afff79..96f07bc3 100644
      +--- a/qtwayland/src/client/qwaylanddatasource_p.h
      ++++ b/qtwayland/src/client/qwaylanddatasource_p.h
      +@@ -77,17 +77,25 @@ public:
      +     QMimeData *mimeData() const;
      + 
      + Q_SIGNALS:
      +-    void targetChanged(const QString &mime_type);
      +     void cancelled();
      ++    void finished();
      ++
      ++    void dndResponseUpdated(bool accepted, Qt::DropAction action);
      ++    void dndDropped(bool accepted, Qt::DropAction action);
      + 
      + protected:
      +     void data_source_cancelled() override;
      +     void data_source_send(const QString &mime_type, int32_t fd) override;
      +     void data_source_target(const QString &mime_type) override;
      ++    void data_source_dnd_drop_performed() override;
      ++    void data_source_dnd_finished() override;
      ++    void data_source_action(uint32_t action) override;
      + 
      + private:
      +     QWaylandDisplay *m_display = nullptr;
      +     QMimeData *m_mime_data = nullptr;
      ++    bool m_accepted = false;
      ++    Qt::DropAction m_dropAction = Qt::IgnoreAction;
      + };
      + 
      + }
      +diff --git a/qtwayland/src/client/qwaylanddisplay.cpp b/qtwayland/src/client/qwaylanddisplay.cpp
      +index f10c1f79..c01e238b 100644
      +--- a/qtwayland/src/client/qwaylanddisplay.cpp
      ++++ b/qtwayland/src/client/qwaylanddisplay.cpp
      +@@ -85,10 +85,203 @@
      + 
      + #include 
      + 
      ++#include  // for std::tie
      ++
      ++static void checkWaylandError(struct wl_display *display)
      ++{
      ++    int ecode = wl_display_get_error(display);
      ++    if ((ecode == EPIPE || ecode == ECONNRESET)) {
      ++        // special case this to provide a nicer error
      ++        qWarning("The Wayland connection broke. Did the Wayland compositor die?");
      ++    } else {
      ++        qWarning("The Wayland connection experienced a fatal error: %s", strerror(ecode));
      ++    }
      ++    _exit(1);
      ++}
      ++
      + QT_BEGIN_NAMESPACE
      + 
      + namespace QtWaylandClient {
      + 
      ++class EventThread : public QThread
      ++{
      ++    Q_OBJECT
      ++public:
      ++    enum OperatingMode {
      ++        EmitToDispatch, // Emit the signal, allow dispatching in a differnt thread.
      ++        SelfDispatch, // Dispatch the events inside this thread.
      ++    };
      ++
      ++    EventThread(struct wl_display * wl, struct wl_event_queue * ev_queue,
      ++                OperatingMode mode)
      ++        : m_fd(wl_display_get_fd(wl))
      ++        , m_pipefd{ -1, -1 }
      ++        , m_wldisplay(wl)
      ++        , m_wlevqueue(ev_queue)
      ++        , m_mode(mode)
      ++        , m_reading(true)
      ++        , m_quitting(false)
      ++    {
      ++        setObjectName(QStringLiteral("WaylandEventThread"));
      ++    }
      ++
      ++    void readAndDispatchEvents()
      ++    {
      ++        /*
      ++         * Dispatch pending events and flush the requests at least once. If the event thread
      ++         * is not reading, try to call _prepare_read() to allow the event thread to poll().
      ++         * If that fails, re-try dispatch & flush again until _prepare_read() is successful.
      ++         *
      ++         * This allow any call to readAndDispatchEvents() to start event thread's polling,
      ++         * not only the one issued from event thread's waitForReading(), which means functions
      ++         * called from dispatch_pending() can safely spin an event loop.
      ++         */
      ++        for (;;) {
      ++            if (dispatchQueuePending() < 0) {
      ++                checkWaylandError(m_wldisplay);
      ++                return;
      ++            }
      ++
      ++            wl_display_flush(m_wldisplay);
      ++
      ++            // We have to check if event thread is reading every time we dispatch
      ++            // something, as that may recursively call this function.
      ++            if (m_reading.loadAcquire())
      ++                break;
      ++
      ++            if (prepareReadQueue() == 0) {
      ++                QMutexLocker l(&m_mutex);
      ++                m_reading.storeRelease(true);
      ++                m_cond.wakeOne();
      ++                break;
      ++            }
      ++        }
      ++    }
      ++
      ++    void stop()
      ++    {
      ++        // We have to both write to the pipe and set the flag, as the thread may be
      ++        // either in the poll() or waiting for _prepare_read().
      ++        if (m_pipefd[1] != -1 && write(m_pipefd[1], "\0", 1) == -1)
      ++            qWarning("Failed to write to the pipe: %s.", strerror(errno));
      ++
      ++        {
      ++            QMutexLocker l(&m_mutex);
      ++            m_quitting = true;
      ++            m_cond.wakeOne();
      ++        }
      ++
      ++        wait();
      ++    }
      ++
      ++Q_SIGNALS:
      ++    void needReadAndDispatch();
      ++
      ++protected:
      ++    void run() override
      ++    {
      ++        // we use this pipe to make the loop exit otherwise if we simply used a flag on the loop condition, if stop() gets
      ++        // called while poll() is blocking the thread will never quit since there are no wayland messages coming anymore.
      ++        struct Pipe
      ++        {
      ++            Pipe(int *fds)
      ++                : fds(fds)
      ++            {
      ++                if (qt_safe_pipe(fds) != 0)
      ++                    qWarning("Pipe creation failed. Quitting may hang.");
      ++            }
      ++            ~Pipe()
      ++            {
      ++                if (fds[0] != -1) {
      ++                    close(fds[0]);
      ++                    close(fds[1]);
      ++                }
      ++            }
      ++
      ++            int *fds;
      ++        } pipe(m_pipefd);
      ++
      ++        // Make the main thread call wl_prepare_read(), dispatch the pending messages and flush the
      ++        // outbound ones. Wait until it's done before proceeding, unless we're told to quit.
      ++        while (waitForReading()) {
      ++            pollfd fds[2] = { { m_fd, POLLIN, 0 }, { m_pipefd[0], POLLIN, 0 } };
      ++            poll(fds, 2, -1);
      ++
      ++            if (fds[1].revents & POLLIN) {
      ++                // we don't really care to read the byte that was written here since we're closing down
      ++                wl_display_cancel_read(m_wldisplay);
      ++                break;
      ++            }
      ++
      ++            if (fds[0].revents & POLLIN)
      ++                wl_display_read_events(m_wldisplay);
      ++                // The polll was succesfull and the event thread did the wl_display_read_events(). On the next iteration of the loop
      ++                // the event sent to the main thread will cause it to dispatch the messages just read, unless the loop exits in which
      ++                // case we don't care anymore about them.
      ++            else
      ++                wl_display_cancel_read(m_wldisplay);
      ++        }
      ++    }
      ++
      ++private:
      ++    bool waitForReading()
      ++    {
      ++        Q_ASSERT(QThread::currentThread() == this);
      ++
      ++        m_reading.storeRelease(false);
      ++
      ++        if (m_mode == SelfDispatch) {
      ++            readAndDispatchEvents();
      ++        } else {
      ++            Q_EMIT needReadAndDispatch();
      ++
      ++            QMutexLocker lock(&m_mutex);
      ++            // m_reading might be set from our emit or some other invocation of
      ++            // readAndDispatchEvents().
      ++            while (!m_reading.loadRelaxed() && !m_quitting)
      ++                m_cond.wait(&m_mutex);
      ++        }
      ++
      ++        return !m_quitting;
      ++    }
      ++
      ++    int dispatchQueuePending()
      ++    {
      ++        if (m_wlevqueue)
      ++            return wl_display_dispatch_queue_pending(m_wldisplay, m_wlevqueue);
      ++        else
      ++            return wl_display_dispatch_pending(m_wldisplay);
      ++    }
      ++
      ++    int prepareReadQueue()
      ++    {
      ++        if (m_wlevqueue)
      ++            return wl_display_prepare_read_queue(m_wldisplay, m_wlevqueue);
      ++        else
      ++            return wl_display_prepare_read(m_wldisplay);
      ++    }
      ++
      ++    int m_fd;
      ++    int m_pipefd[2];
      ++    wl_display *m_wldisplay;
      ++    wl_event_queue *m_wlevqueue;
      ++    OperatingMode m_mode;
      ++
      ++    /* Concurrency note when operating in EmitToDispatch mode:
      ++     * m_reading is set to false inside event thread's waitForReading(), and is
      ++     * set to true inside main thread's readAndDispatchEvents().
      ++     * The lock is not taken when setting m_reading to false, as the main thread
      ++     * is not actively waiting for it to turn false. However, the lock is taken
      ++     * inside readAndDispatchEvents() before setting m_reading to true,
      ++     * as the event thread is actively waiting for it under the wait condition.
      ++     */
      ++
      ++    QAtomicInteger m_reading;
      ++    bool m_quitting;
      ++    QMutex m_mutex;
      ++    QWaitCondition m_cond;
      ++};
      ++
      + Q_LOGGING_CATEGORY(lcQpaWayland, "qt.qpa.wayland"); // for general (uncategorized) Wayland platform logging
      + 
      + struct wl_surface *QWaylandDisplay::createSurface(void *handle)
      +@@ -158,17 +351,16 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration)
      +     if (!mXkbContext)
      +         qCWarning(lcQpaWayland, "failed to create xkb context");
      + #endif
      +-
      +-    forceRoundTrip();
      +-
      +-    if (!mWaitingScreens.isEmpty()) {
      +-        // Give wl_output.done and zxdg_output_v1.done events a chance to arrive
      +-        forceRoundTrip();
      +-    }
      + }
      + 
      + QWaylandDisplay::~QWaylandDisplay(void)
      + {
      ++    if (m_eventThread)
      ++        m_eventThread->stop();
      ++
      ++    if (m_frameEventQueueThread)
      ++        m_frameEventQueueThread->stop();
      ++
      +     if (mSyncCallback)
      +         wl_callback_destroy(mSyncCallback);
      + 
      +@@ -187,6 +379,21 @@ QWaylandDisplay::~QWaylandDisplay(void)
      + #endif
      +     if (mDisplay)
      +         wl_display_disconnect(mDisplay);
      ++
      ++    if (m_frameEventQueue)
      ++        wl_event_queue_destroy(m_frameEventQueue);
      ++}
      ++
      ++// Steps which is called just after constructor. This separates registry_global() out of the constructor
      ++// so that factory functions in integration can be overridden.
      ++void QWaylandDisplay::initialize()
      ++{
      ++    forceRoundTrip();
      ++
      ++    if (!mWaitingScreens.isEmpty()) {
      ++        // Give wl_output.done and zxdg_output_v1.done events a chance to arrive
      ++        forceRoundTrip();
      ++    }
      + }
      + 
      + void QWaylandDisplay::ensureScreen()
      +@@ -203,98 +410,37 @@ void QWaylandDisplay::ensureScreen()
      + 
      + void QWaylandDisplay::checkError() const
      + {
      +-    int ecode = wl_display_get_error(mDisplay);
      +-    if ((ecode == EPIPE || ecode == ECONNRESET)) {
      +-        // special case this to provide a nicer error
      +-        qWarning("The Wayland connection broke. Did the Wayland compositor die?");
      +-    } else {
      +-        qWarning("The Wayland connection experienced a fatal error: %s", strerror(ecode));
      +-    }
      +-    _exit(1);
      ++    checkWaylandError(mDisplay);
      + }
      + 
      ++// Called in main thread, either from queued signal or directly.
      + void QWaylandDisplay::flushRequests()
      + {
      +-    if (wl_display_prepare_read(mDisplay) == 0) {
      +-        wl_display_read_events(mDisplay);
      +-    }
      +-
      +-    if (wl_display_dispatch_pending(mDisplay) < 0)
      +-        checkError();
      +-
      +-    {
      +-        QReadLocker locker(&m_frameQueueLock);
      +-        for (const FrameQueue &q : mExternalQueues) {
      +-            QMutexLocker locker(q.mutex);
      +-            while (wl_display_prepare_read_queue(mDisplay, q.queue) != 0)
      +-                wl_display_dispatch_queue_pending(mDisplay, q.queue);
      +-            wl_display_read_events(mDisplay);
      +-            wl_display_dispatch_queue_pending(mDisplay, q.queue);
      +-        }
      +-    }
      +-
      +-    wl_display_flush(mDisplay);
      +-}
      +-
      +-void QWaylandDisplay::blockingReadEvents()
      +-{
      +-    if (wl_display_dispatch(mDisplay) < 0)
      +-        checkError();
      +-}
      +-
      +-void QWaylandDisplay::destroyFrameQueue(const QWaylandDisplay::FrameQueue &q)
      +-{
      +-    QWriteLocker locker(&m_frameQueueLock);
      +-    auto it = std::find_if(mExternalQueues.begin(),
      +-                           mExternalQueues.end(),
      +-                           [&q] (const QWaylandDisplay::FrameQueue &other){ return other.queue == q.queue; });
      +-    Q_ASSERT(it != mExternalQueues.end());
      +-    mExternalQueues.erase(it);
      +-    if (q.queue != nullptr)
      +-        wl_event_queue_destroy(q.queue);
      +-    delete q.mutex;
      ++    m_eventThread->readAndDispatchEvents();
      + }
      + 
      +-QWaylandDisplay::FrameQueue QWaylandDisplay::createFrameQueue()
      ++// We have to wait until we have an eventDispatcher before creating the eventThread,
      ++// otherwise forceRoundTrip() may block inside _events_read() because eventThread is
      ++// polling.
      ++void QWaylandDisplay::initEventThread()
      + {
      +-    QWriteLocker locker(&m_frameQueueLock);
      +-    FrameQueue q{createEventQueue()};
      +-    mExternalQueues.append(q);
      +-    return q;
      +-}
      ++    m_eventThread.reset(
      ++            new EventThread(mDisplay, /* default queue */ nullptr, EventThread::EmitToDispatch));
      ++    connect(m_eventThread.get(), &EventThread::needReadAndDispatch, this,
      ++            &QWaylandDisplay::flushRequests, Qt::QueuedConnection);
      ++    m_eventThread->start();
      + 
      +-wl_event_queue *QWaylandDisplay::createEventQueue()
      +-{
      +-    return wl_display_create_queue(mDisplay);
      ++    // wl_display_disconnect() free this.
      ++    m_frameEventQueue = wl_display_create_queue(mDisplay);
      ++    m_frameEventQueueThread.reset(
      ++            new EventThread(mDisplay, m_frameEventQueue, EventThread::SelfDispatch));
      ++    m_frameEventQueueThread->start();
      + }
      + 
      +-void QWaylandDisplay::dispatchQueueWhile(wl_event_queue *queue, std::function condition, int timeout)
      ++void QWaylandDisplay::blockingReadEvents()
      + {
      +-    if (!condition())
      +-        return;
      +-
      +-    QElapsedTimer timer;
      +-    timer.start();
      +-    struct pollfd pFd = qt_make_pollfd(wl_display_get_fd(mDisplay), POLLIN);
      +-    while (timeout == -1 || timer.elapsed() < timeout) {
      +-        while (wl_display_prepare_read_queue(mDisplay, queue) != 0)
      +-            wl_display_dispatch_queue_pending(mDisplay, queue);
      +-
      +-        wl_display_flush(mDisplay);
      +-
      +-        const int remaining = qMax(timeout - timer.elapsed(), 0ll);
      +-        const int pollTimeout = timeout == -1 ? -1 : remaining;
      +-        if (qt_poll_msecs(&pFd, 1, pollTimeout) > 0)
      +-            wl_display_read_events(mDisplay);
      +-        else
      +-            wl_display_cancel_read(mDisplay);
      +-
      +-        if (wl_display_dispatch_queue_pending(mDisplay, queue) < 0)
      +-            checkError();
      +-
      +-        if (!condition())
      +-            break;
      +-    }
      ++    if (wl_display_dispatch(mDisplay) < 0)
      ++        checkWaylandError(mDisplay);
      + }
      + 
      + QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const
      +@@ -345,7 +491,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
      +     if (interface == QStringLiteral("wl_output")) {
      +         mWaitingScreens << new QWaylandScreen(this, version, id);
      +     } else if (interface == QStringLiteral("wl_compositor")) {
      +-        mCompositorVersion = qMin((int)version, 3);
      ++        mCompositorVersion = qMin((int)version, 4);
      +         mCompositor.init(registry, id, mCompositorVersion);
      +     } else if (interface == QStringLiteral("wl_shm")) {
      +         mShm.reset(new QWaylandShm(this, version, id));
      +@@ -354,7 +500,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
      +         mInputDevices.append(inputDevice);
      + #if QT_CONFIG(wayland_datadevice)
      +     } else if (interface == QStringLiteral("wl_data_device_manager")) {
      +-        mDndSelectionHandler.reset(new QWaylandDataDeviceManager(this, id));
      ++        mDndSelectionHandler.reset(new QWaylandDataDeviceManager(this, version, id));
      + #endif
      +     } else if (interface == QStringLiteral("qt_surface_extension")) {
      +         mWindowExtension.reset(new QtWayland::qt_surface_extension(registry, id, 1));
      +@@ -369,6 +515,8 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
      + #if QT_CONFIG(wayland_client_primary_selection)
      +     } else if (interface == QStringLiteral("zwp_primary_selection_device_manager_v1")) {
      +         mPrimarySelectionManager.reset(new QWaylandPrimarySelectionDeviceManagerV1(this, id, 1));
      ++        for (QWaylandInputDevice *inputDevice : qAsConst(mInputDevices))
      ++            inputDevice->setPrimarySelectionDevice(mPrimarySelectionManager->createDevice(inputDevice));
      + #endif
      +     } else if (interface == QStringLiteral("zwp_text_input_manager_v2") && !mClientSideInputContextRequested) {
      +         mTextInputManager.reset(new QtWayland::zwp_text_input_manager_v2(registry, id, 1));
      +@@ -427,6 +575,13 @@ void QWaylandDisplay::registry_global_remove(uint32_t id)
      +                     inputDevice->setTextInput(nullptr);
      +                 mWaylandIntegration->reconfigureInputContext();
      +             }
      ++#if QT_CONFIG(wayland_client_primary_selection)
      ++            if (global.interface == QStringLiteral("zwp_primary_selection_device_manager_v1")) {
      ++                mPrimarySelectionManager.reset();
      ++                for (QWaylandInputDevice *inputDevice : qAsConst(mInputDevices))
      ++                    inputDevice->setPrimarySelectionDevice(nullptr);
      ++            }
      ++#endif
      +             mGlobals.removeAt(i);
      +             break;
      +         }
      +@@ -452,9 +607,10 @@ void QWaylandDisplay::addRegistryListener(RegistryListener listener, void *data)
      + 
      + void QWaylandDisplay::removeListener(RegistryListener listener, void *data)
      + {
      +-    std::remove_if(mRegistryListeners.begin(), mRegistryListeners.end(), [=](Listener l){
      ++    auto iter = std::remove_if(mRegistryListeners.begin(), mRegistryListeners.end(), [=](Listener l){
      +         return (l.listener == listener && l.data == data);
      +     });
      ++    mRegistryListeners.erase(iter, mRegistryListeners.end());
      + }
      + 
      + uint32_t QWaylandDisplay::currentTimeMillisec()
      +@@ -467,50 +623,9 @@ uint32_t QWaylandDisplay::currentTimeMillisec()
      +     return 0;
      + }
      + 
      +-static void
      +-sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
      +-{
      +-    Q_UNUSED(serial)
      +-    bool *done = static_cast(data);
      +-
      +-    *done = true;
      +-
      +-    // If the wl_callback done event is received after the condition check in the while loop in
      +-    // forceRoundTrip(), but before the call to processEvents, the call to processEvents may block
      +-    // forever if no more events are posted (eventhough the callback is handled in response to the
      +-    // aboutToBlock signal). Hence, we wake up the event dispatcher so forceRoundTrip may return.
      +-    // (QTBUG-64696)
      +-    if (auto *dispatcher = QThread::currentThread()->eventDispatcher())
      +-        dispatcher->wakeUp();
      +-
      +-    wl_callback_destroy(callback);
      +-}
      +-
      +-static const struct wl_callback_listener sync_listener = {
      +-    sync_callback
      +-};
      +-
      + void QWaylandDisplay::forceRoundTrip()
      + {
      +-    // wl_display_roundtrip() works on the main queue only,
      +-    // but we use a separate one, so basically reimplement it here
      +-    int ret = 0;
      +-    bool done = false;
      +-    wl_callback *callback = wl_display_sync(mDisplay);
      +-    wl_callback_add_listener(callback, &sync_listener, &done);
      +-    flushRequests();
      +-    if (QThread::currentThread()->eventDispatcher()) {
      +-        while (!done && ret >= 0) {
      +-            QThread::currentThread()->eventDispatcher()->processEvents(QEventLoop::WaitForMoreEvents);
      +-            ret = wl_display_dispatch_pending(mDisplay);
      +-        }
      +-    } else {
      +-        while (!done && ret >= 0)
      +-            ret = wl_display_dispatch(mDisplay);
      +-    }
      +-
      +-    if (ret == -1 && !done)
      +-        wl_callback_destroy(callback);
      ++     wl_display_roundtrip(mDisplay);
      + }
      + 
      + bool QWaylandDisplay::supportsWindowDecoration() const
      +@@ -574,14 +689,10 @@ void QWaylandDisplay::handleKeyboardFocusChanged(QWaylandInputDevice *inputDevic
      +     if (mLastKeyboardFocus == keyboardFocus)
      +         return;
      + 
      +-    if (mWaylandIntegration->mShellIntegration) {
      +-        mWaylandIntegration->mShellIntegration->handleKeyboardFocusChanged(keyboardFocus, mLastKeyboardFocus);
      +-    } else {
      +-        if (keyboardFocus)
      +-            handleWindowActivated(keyboardFocus);
      +-        if (mLastKeyboardFocus)
      +-            handleWindowDeactivated(mLastKeyboardFocus);
      +-    }
      ++    if (keyboardFocus)
      ++        handleWindowActivated(keyboardFocus);
      ++    if (mLastKeyboardFocus)
      ++        handleWindowDeactivated(mLastKeyboardFocus);
      + 
      +     mLastKeyboardFocus = keyboardFocus;
      + }
      +@@ -600,6 +711,19 @@ void QWaylandDisplay::handleWaylandSync()
      +     QWindow *activeWindow = mActiveWindows.empty() ? nullptr : mActiveWindows.last()->window();
      +     if (activeWindow != QGuiApplication::focusWindow())
      +         QWindowSystemInterface::handleWindowActivated(activeWindow);
      ++
      ++    if (!activeWindow) {
      ++        if (lastInputDevice()) {
      ++#if QT_CONFIG(clipboard)
      ++            if (auto *dataDevice = lastInputDevice()->dataDevice())
      ++                dataDevice->invalidateSelectionOffer();
      ++#endif
      ++#if QT_CONFIG(wayland_client_primary_selection)
      ++            if (auto *device = lastInputDevice()->primarySelectionDevice())
      ++                device->invalidateSelectionOffer();
      ++#endif
      ++        }
      ++    }
      + }
      + 
      + const wl_callback_listener QWaylandDisplay::syncCallbackListener = {
      +@@ -626,6 +750,13 @@ QWaylandInputDevice *QWaylandDisplay::defaultInputDevice() const
      +     return mInputDevices.isEmpty() ? 0 : mInputDevices.first();
      + }
      + 
      ++bool QWaylandDisplay::isKeyboardAvailable() const
      ++{
      ++    return std::any_of(
      ++            mInputDevices.constBegin(), mInputDevices.constEnd(),
      ++            [this](const QWaylandInputDevice *device) { return device->keyboard() != nullptr; });
      ++}
      ++
      + #if QT_CONFIG(cursor)
      + 
      + QWaylandCursor *QWaylandDisplay::waylandCursor()
      +@@ -652,4 +783,6 @@ QWaylandCursorTheme *QWaylandDisplay::loadCursorTheme(const QString &name, int p
      + 
      + } // namespace QtWaylandClient
      + 
      ++#include "qwaylanddisplay.moc"
      ++
      + QT_END_NAMESPACE
      +diff --git a/qtwayland/src/client/qwaylanddisplay_p.h b/qtwayland/src/client/qwaylanddisplay_p.h
      +index 3b092bc8..42bc661d 100644
      +--- a/qtwayland/src/client/qwaylanddisplay_p.h
      ++++ b/qtwayland/src/client/qwaylanddisplay_p.h
      +@@ -109,6 +109,7 @@ class QWaylandSurface;
      + class QWaylandShellIntegration;
      + class QWaylandCursor;
      + class QWaylandCursorTheme;
      ++class EventThread;
      + 
      + typedef void (*RegistryListener)(void *data,
      +                                  struct wl_registry *registry,
      +@@ -120,15 +121,11 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandDisplay : public QObject, public QtWayland
      +     Q_OBJECT
      + 
      + public:
      +-    struct FrameQueue {
      +-        FrameQueue(wl_event_queue *q = nullptr) : queue(q), mutex(new QMutex) {}
      +-        wl_event_queue *queue;
      +-        QMutex *mutex;
      +-    };
      +-
      +     QWaylandDisplay(QWaylandIntegration *waylandIntegration);
      +     ~QWaylandDisplay(void) override;
      + 
      ++    void initialize();
      ++
      + #if QT_CONFIG(xkbcommon)
      +     struct xkb_context *xkbContext() const { return mXkbContext.get(); }
      + #endif
      +@@ -210,11 +207,11 @@ public:
      +     void handleKeyboardFocusChanged(QWaylandInputDevice *inputDevice);
      +     void handleWindowDestroyed(QWaylandWindow *window);
      + 
      +-    wl_event_queue *createEventQueue();
      +-    FrameQueue createFrameQueue();
      +-    void destroyFrameQueue(const FrameQueue &q);
      +-    void dispatchQueueWhile(wl_event_queue *queue, std::function condition, int timeout = -1);
      ++    wl_event_queue *frameEventQueue() { return m_frameEventQueue; };
      ++
      ++    bool isKeyboardAvailable() const;
      + 
      ++    void initEventThread();
      + public slots:
      +     void blockingReadEvents();
      +     void flushRequests();
      +@@ -237,6 +234,9 @@ private:
      +     };
      + 
      +     struct wl_display *mDisplay = nullptr;
      ++    QScopedPointer m_eventThread;
      ++    wl_event_queue *m_frameEventQueue = nullptr;
      ++    QScopedPointer m_frameEventQueueThread;
      +     QtWayland::wl_compositor mCompositor;
      +     QScopedPointer mShm;
      +     QList mWaitingScreens;
      +@@ -273,11 +273,9 @@ private:
      +     QWaylandInputDevice *mLastInputDevice = nullptr;
      +     QPointer mLastInputWindow;
      +     QPointer mLastKeyboardFocus;
      +-    QVector mActiveWindows;
      +-    QVector mExternalQueues;
      ++    QList mActiveWindows;
      +     struct wl_callback *mSyncCallback = nullptr;
      +     static const wl_callback_listener syncCallbackListener;
      +-    QReadWriteLock m_frameQueueLock;
      + 
      +     bool mClientSideInputContextRequested = !QPlatformInputContextFactory::requested().isNull();
      + 
      +diff --git a/qtwayland/src/client/qwaylanddnd.cpp b/qtwayland/src/client/qwaylanddnd.cpp
      +index 6535aa16..7c53f5fa 100644
      +--- a/qtwayland/src/client/qwaylanddnd.cpp
      ++++ b/qtwayland/src/client/qwaylanddnd.cpp
      +@@ -66,7 +66,7 @@ void QWaylandDrag::startDrag()
      + {
      +     QBasicDrag::startDrag();
      +     QWaylandWindow *icon = static_cast(shapedPixmapWindow()->handle());
      +-    if (m_display->currentInputDevice()->dataDevice()->startDrag(drag()->mimeData(), icon)) {
      ++    if (m_display->currentInputDevice()->dataDevice()->startDrag(drag()->mimeData(), drag()->supportedActions(), icon)) {
      +         icon->addAttachOffset(-drag()->hotSpot());
      +     } else {
      +         // Cancelling immediately does not work, since the event loop for QDrag::exec is started
      +@@ -80,6 +80,9 @@ void QWaylandDrag::cancel()
      +     QBasicDrag::cancel();
      + 
      +     m_display->currentInputDevice()->dataDevice()->cancelDrag();
      ++
      ++    if (drag())
      ++        drag()->deleteLater();
      + }
      + 
      + void QWaylandDrag::move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
      +@@ -103,33 +106,41 @@ void QWaylandDrag::endDrag()
      +     m_display->currentInputDevice()->handleEndDrag();
      + }
      + 
      +-void QWaylandDrag::updateTarget(const QString &mimeType)
      ++void QWaylandDrag::setResponse(bool accepted)
      + {
      +-    setCanDrop(!mimeType.isEmpty());
      +-
      +-    if (canDrop()) {
      +-        updateCursor(defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers()));
      +-    } else {
      +-        updateCursor(Qt::IgnoreAction);
      +-    }
      ++    // This method is used for old DataDevices where the drag action is not communicated
      ++    Qt::DropAction action = defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers());
      ++    setResponse(QPlatformDropQtResponse(accepted, action));
      + }
      + 
      +-void QWaylandDrag::setResponse(const QPlatformDragQtResponse &response)
      ++void QWaylandDrag::setResponse(const QPlatformDropQtResponse &response)
      + {
      +     setCanDrop(response.isAccepted());
      + 
      +     if (canDrop()) {
      +-        updateCursor(defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers()));
      ++        updateCursor(response.acceptedAction());
      +     } else {
      +         updateCursor(Qt::IgnoreAction);
      +     }
      + }
      + 
      +-void QWaylandDrag::finishDrag(const QPlatformDropQtResponse &response)
      ++void QWaylandDrag::setDropResponse(const QPlatformDropQtResponse &response)
      + {
      +     setExecutedDropAction(response.acceptedAction());
      ++}
      ++
      ++void QWaylandDrag::finishDrag()
      ++{
      +     QKeyEvent event(QEvent::KeyPress, Qt::Key_Escape, Qt::NoModifier);
      +     eventFilter(shapedPixmapWindow(), &event);
      ++
      ++    if (drag())
      ++        drag()->deleteLater();
      ++}
      ++
      ++bool QWaylandDrag::ownsDragObject() const
      ++{
      ++    return true;
      + }
      + 
      + }
      +diff --git a/qtwayland/src/client/qwaylanddnd_p.h b/qtwayland/src/client/qwaylanddnd_p.h
      +index 474fe2ab..46f629ac 100644
      +--- a/qtwayland/src/client/qwaylanddnd_p.h
      ++++ b/qtwayland/src/client/qwaylanddnd_p.h
      +@@ -71,9 +71,10 @@ public:
      +     QWaylandDrag(QWaylandDisplay *display);
      +     ~QWaylandDrag() override;
      + 
      +-    void updateTarget(const QString &mimeType);
      +-    void setResponse(const QPlatformDragQtResponse &response);
      +-    void finishDrag(const QPlatformDropQtResponse &response);
      ++    void setResponse(bool accepted);
      ++    void setResponse(const QPlatformDropQtResponse &response);
      ++    void setDropResponse(const QPlatformDropQtResponse &response);
      ++    void finishDrag();
      + 
      + protected:
      +     void startDrag() override;
      +@@ -82,6 +83,7 @@ protected:
      +     void drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override;
      +     void endDrag() override;
      + 
      ++    bool ownsDragObject() const override;
      + 
      + private:
      +     QWaylandDisplay *m_display = nullptr;
      +diff --git a/qtwayland/src/client/qwaylandinputdevice.cpp b/qtwayland/src/client/qwaylandinputdevice.cpp
      +index 613fe862..4b90de84 100644
      +--- a/qtwayland/src/client/qwaylandinputdevice.cpp
      ++++ b/qtwayland/src/client/qwaylandinputdevice.cpp
      +@@ -685,6 +685,11 @@ public:
      + 
      + void QWaylandInputDevice::Pointer::pointer_leave(uint32_t time, struct wl_surface *surface)
      + {
      ++    invalidateFocus();
      ++    mButtons = Qt::NoButton;
      ++
      ++    mParent->mTime = time;
      ++
      +     // The event may arrive after destroying the window, indicated by
      +     // a null surface.
      +     if (!surface)
      +@@ -696,11 +701,6 @@ void QWaylandInputDevice::Pointer::pointer_leave(uint32_t time, struct wl_surfac
      + 
      +     if (!QWaylandWindow::mouseGrab())
      +         setFrameEvent(new LeaveEvent(window, mSurfacePos, mGlobalPos));
      +-
      +-    invalidateFocus();
      +-    mButtons = Qt::NoButton;
      +-
      +-    mParent->mTime = time;
      + }
      + 
      + class MotionEvent : public QWaylandPointerEvent
      +@@ -1300,14 +1300,6 @@ void QWaylandInputDevice::Keyboard::handleFocusDestroyed()
      + void QWaylandInputDevice::Keyboard::handleFocusLost()
      + {
      +     mFocus = nullptr;
      +-#if QT_CONFIG(clipboard)
      +-    if (auto *dataDevice = mParent->dataDevice())
      +-        dataDevice->invalidateSelectionOffer();
      +-#endif
      +-#if QT_CONFIG(wayland_client_primary_selection)
      +-    if (auto *device = mParent->primarySelectionDevice())
      +-        device->invalidateSelectionOffer();
      +-#endif
      +     mParent->mQDisplay->handleKeyboardFocusChanged(mParent);
      +     mRepeatTimer.stop();
      + }
      +@@ -1396,6 +1388,7 @@ void QWaylandInputDevice::Touch::touch_cancel()
      +     if (touchExt)
      +         touchExt->touchCanceled();
      + 
      ++    mFocus = nullptr;
      +     QWindowSystemInterface::handleTouchCancelEvent(nullptr, mParent->mTouchDevice);
      + }
      + 
      +diff --git a/qtwayland/src/client/qwaylandintegration.cpp b/qtwayland/src/client/qwaylandintegration.cpp
      +index c53ccb78..54861600 100644
      +--- a/qtwayland/src/client/qwaylandintegration.cpp
      ++++ b/qtwayland/src/client/qwaylandintegration.cpp
      +@@ -125,6 +125,9 @@ QWaylandIntegration::QWaylandIntegration()
      + #endif
      + 
      +     reconfigureInputContext();
      ++
      ++    QWaylandWindow::fixedToplevelPositions =
      ++            !qEnvironmentVariableIsSet("QT_WAYLAND_DISABLE_FIXED_POSITIONS");
      + }
      + 
      + QWaylandIntegration::~QWaylandIntegration()
      +@@ -192,14 +195,18 @@ QAbstractEventDispatcher *QWaylandIntegration::createEventDispatcher() const
      + 
      + void QWaylandIntegration::initialize()
      + {
      ++    mDisplay->initEventThread();
      ++
      ++    // Call after eventDispatcher is fully connected, for QWaylandDisplay::forceRoundTrip()
      ++    mDisplay->initialize();
      ++
      ++    // But the aboutToBlock() and awake() should be connected after initializePlatform().
      ++    // Otherwise the connected flushRequests() may consumes up all events before processEvents starts to wait,
      ++    // so that processEvents(QEventLoop::WaitForMoreEvents) may be blocked in the forceRoundTrip().
      +     QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
      +     QObject::connect(dispatcher, SIGNAL(aboutToBlock()), mDisplay.data(), SLOT(flushRequests()));
      +     QObject::connect(dispatcher, SIGNAL(awake()), mDisplay.data(), SLOT(flushRequests()));
      + 
      +-    int fd = wl_display_get_fd(mDisplay->wl_display());
      +-    QSocketNotifier *sn = new QSocketNotifier(fd, QSocketNotifier::Read, mDisplay.data());
      +-    QObject::connect(sn, SIGNAL(activated(QSocketDescriptor)), mDisplay.data(), SLOT(flushRequests()));
      +-
      +     // Qt does not support running with no screens
      +     mDisplay->ensureScreen();
      + }
      +@@ -262,6 +269,14 @@ QWaylandDisplay *QWaylandIntegration::display() const
      +     return mDisplay.data();
      + }
      + 
      ++Qt::KeyboardModifiers QWaylandIntegration::queryKeyboardModifiers() const
      ++{
      ++    if (auto *seat = mDisplay->currentInputDevice()) {
      ++        return seat->modifiers();
      ++    }
      ++    return Qt::NoModifier;
      ++}
      ++
      + QList QWaylandIntegration::possibleKeys(const QKeyEvent *event) const
      + {
      +     if (auto *seat = mDisplay->currentInputDevice())
      +@@ -479,7 +494,7 @@ void QWaylandIntegration::reconfigureInputContext()
      +     }
      + #endif
      + 
      +-    qCDebug(lcQpaWayland) << "using input method:" << inputContext()->metaObject()->className();
      ++    qCDebug(lcQpaWayland) << "using input method:" << (inputContext() ? inputContext()->metaObject()->className() : "");
      + }
      + 
      + QWaylandShellIntegration *QWaylandIntegration::createShellIntegration(const QString &integrationName)
      +diff --git a/qtwayland/src/client/qwaylandintegration_p.h b/qtwayland/src/client/qwaylandintegration_p.h
      +index ff70ae25..73b80658 100644
      +--- a/qtwayland/src/client/qwaylandintegration_p.h
      ++++ b/qtwayland/src/client/qwaylandintegration_p.h
      +@@ -107,6 +107,8 @@ public:
      + 
      +     QWaylandDisplay *display() const;
      + 
      ++    Qt::KeyboardModifiers queryKeyboardModifiers() const override;
      ++
      +     QList possibleKeys(const QKeyEvent *event) const override;
      + 
      +     QStringList themeNames() const override;
      +diff --git a/qtwayland/src/client/qwaylandprimaryselectionv1.cpp b/qtwayland/src/client/qwaylandprimaryselectionv1.cpp
      +index 832f9678..ea508771 100644
      +--- a/qtwayland/src/client/qwaylandprimaryselectionv1.cpp
      ++++ b/qtwayland/src/client/qwaylandprimaryselectionv1.cpp
      +@@ -54,11 +54,6 @@ QWaylandPrimarySelectionDeviceManagerV1::QWaylandPrimarySelectionDeviceManagerV1
      +     : zwp_primary_selection_device_manager_v1(display->wl_registry(), id, qMin(version, uint(1)))
      +     , m_display(display)
      + {
      +-    // Create devices for all seats.
      +-    // This only works if we get the global before all devices
      +-    const auto seats = m_display->inputDevices();
      +-    for (auto *seat : seats)
      +-        seat->setPrimarySelectionDevice(createDevice(seat));
      + }
      + 
      + QWaylandPrimarySelectionDeviceV1 *QWaylandPrimarySelectionDeviceManagerV1::createDevice(QWaylandInputDevice *seat)
      +diff --git a/qtwayland/src/client/qwaylandscreen.cpp b/qtwayland/src/client/qwaylandscreen.cpp
      +index 6cb337de..5537dafd 100644
      +--- a/qtwayland/src/client/qwaylandscreen.cpp
      ++++ b/qtwayland/src/client/qwaylandscreen.cpp
      +@@ -60,7 +60,7 @@ QWaylandXdgOutputManagerV1::QWaylandXdgOutputManagerV1(QWaylandDisplay* display,
      + }
      + 
      + QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uint32_t id)
      +-    : QtWayland::wl_output(waylandDisplay->wl_registry(), id, qMin(version, 2))
      ++    : QtWayland::wl_output(waylandDisplay->wl_registry(), id, qMin(version, 3))
      +     , m_outputId(id)
      +     , mWaylandDisplay(waylandDisplay)
      +     , mOutputName(QStringLiteral("Screen%1").arg(id))
      +@@ -72,7 +72,7 @@ QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uin
      +         qCWarning(lcQpaWayland) << "wl_output done event not supported by compositor,"
      +                                 << "QScreen may not work correctly";
      +         mWaylandDisplay->forceRoundTrip(); // Give the compositor a chance to send geometry etc.
      +-        mOutputDone = true; // Fake the done event
      ++        mProcessedEvents |= OutputDoneEvent; // Fake the done event
      +         maybeInitialize();
      +     }
      + }
      +@@ -81,16 +81,29 @@ QWaylandScreen::~QWaylandScreen()
      + {
      +     if (zxdg_output_v1::isInitialized())
      +         zxdg_output_v1::destroy();
      ++    if (wl_output::isInitialized() && wl_output_get_version(wl_output::object()) >= WL_OUTPUT_RELEASE_SINCE_VERSION)
      ++        wl_output::release();
      ++}
      ++
      ++uint QWaylandScreen::requiredEvents() const
      ++{
      ++    uint ret = OutputDoneEvent;
      ++
      ++    if (mWaylandDisplay->xdgOutputManager()) {
      ++        ret |= XdgOutputNameEvent;
      ++
      ++        if (mWaylandDisplay->xdgOutputManager()->version() < 3)
      ++            ret |= XdgOutputDoneEvent;
      ++    }
      ++    return ret;
      + }
      + 
      + void QWaylandScreen::maybeInitialize()
      + {
      +     Q_ASSERT(!mInitialized);
      + 
      +-    if (!mOutputDone)
      +-        return;
      +-
      +-    if (mWaylandDisplay->xdgOutputManager() && !mXdgOutputDone)
      ++    const uint requiredEvents = this->requiredEvents();
      ++    if ((mProcessedEvents & requiredEvents) != requiredEvents)
      +         return;
      + 
      +     mInitialized = true;
      +@@ -276,9 +289,8 @@ void QWaylandScreen::output_scale(int32_t factor)
      + 
      + void QWaylandScreen::output_done()
      + {
      +-    mOutputDone = true;
      +-    if (zxdg_output_v1::isInitialized() && mWaylandDisplay->xdgOutputManager()->version() >= 3)
      +-        mXdgOutputDone = true;
      ++    mProcessedEvents |= OutputDoneEvent;
      ++
      +     if (mInitialized) {
      +         updateOutputProperties();
      +         if (zxdg_output_v1::isInitialized())
      +@@ -339,7 +351,7 @@ void QWaylandScreen::zxdg_output_v1_done()
      +     if (Q_UNLIKELY(mWaylandDisplay->xdgOutputManager()->version() >= 3))
      +         qWarning(lcQpaWayland) << "zxdg_output_v1.done received on version 3 or newer, this is most likely a bug in the compositor";
      + 
      +-    mXdgOutputDone = true;
      ++    mProcessedEvents |= XdgOutputDoneEvent;
      +     if (mInitialized)
      +         updateXdgOutputProperties();
      +     else
      +@@ -348,7 +360,11 @@ void QWaylandScreen::zxdg_output_v1_done()
      + 
      + void QWaylandScreen::zxdg_output_v1_name(const QString &name)
      + {
      ++    if (Q_UNLIKELY(mInitialized))
      ++        qWarning(lcQpaWayland) << "zxdg_output_v1.name received after output has been initialized, this is most likely a bug in the compositor";
      ++
      +     mOutputName = name;
      ++    mProcessedEvents |= XdgOutputNameEvent;
      + }
      + 
      + void QWaylandScreen::updateXdgOutputProperties()
      +diff --git a/qtwayland/src/client/qwaylandscreen_p.h b/qtwayland/src/client/qwaylandscreen_p.h
      +index df1c94f2..050cfdc0 100644
      +--- a/qtwayland/src/client/qwaylandscreen_p.h
      ++++ b/qtwayland/src/client/qwaylandscreen_p.h
      +@@ -116,6 +116,13 @@ public:
      +     static QWaylandScreen *fromWlOutput(::wl_output *output);
      + 
      + private:
      ++    enum Event : uint {
      ++        XdgOutputDoneEvent = 0x1,
      ++        OutputDoneEvent = 0x2,
      ++        XdgOutputNameEvent = 0x4,
      ++    };
      ++    uint requiredEvents() const;
      ++
      +     void output_mode(uint32_t flags, int width, int height, int refresh) override;
      +     void output_geometry(int32_t x, int32_t y,
      +                          int32_t width, int32_t height,
      +@@ -148,8 +155,7 @@ private:
      +     QSize mPhysicalSize;
      +     QString mOutputName;
      +     Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation;
      +-    bool mOutputDone = false;
      +-    bool mXdgOutputDone = false;
      ++    uint mProcessedEvents = 0;
      +     bool mInitialized = false;
      + 
      + #if QT_CONFIG(cursor)
      +diff --git a/qtwayland/src/client/qwaylandshmbackingstore.cpp b/qtwayland/src/client/qwaylandshmbackingstore.cpp
      +index dc7ff670..41cffdf7 100644
      +--- a/qtwayland/src/client/qwaylandshmbackingstore.cpp
      ++++ b/qtwayland/src/client/qwaylandshmbackingstore.cpp
      +@@ -52,6 +52,7 @@
      + 
      + #include 
      + 
      ++#include 
      + #include 
      + #include 
      + 
      +@@ -61,6 +62,9 @@
      + #  ifndef MFD_CLOEXEC
      + #    define MFD_CLOEXEC     0x0001U
      + #  endif
      ++#  ifndef MFD_ALLOW_SEALING
      ++#    define MFD_ALLOW_SEALING 0x0002U
      ++#  endif
      + #endif
      + 
      + QT_BEGIN_NAMESPACE
      +@@ -74,8 +78,10 @@ QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display,
      +     int alloc = stride * size.height();
      +     int fd = -1;
      + 
      +-#ifdef SYS_memfd_create
      +-    fd = syscall(SYS_memfd_create, "wayland-shm", MFD_CLOEXEC);
      ++#if defined(SYS_memfd_create) && defined(F_SEAL_SEAL)
      ++    fd = syscall(SYS_memfd_create, "wayland-shm", MFD_CLOEXEC | MFD_ALLOW_SEALING);
      ++    if (fd >= 0)
      ++        fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);
      + #endif
      + 
      +     QScopedPointer filePointer;
      +diff --git a/qtwayland/src/client/qwaylandwindow.cpp b/qtwayland/src/client/qwaylandwindow.cpp
      +index cb82857a..fb2c59dc 100644
      +--- a/qtwayland/src/client/qwaylandwindow.cpp
      ++++ b/qtwayland/src/client/qwaylandwindow.cpp
      +@@ -76,7 +76,6 @@ QWaylandWindow *QWaylandWindow::mMouseGrab = nullptr;
      + QWaylandWindow::QWaylandWindow(QWindow *window, QWaylandDisplay *display)
      +     : QPlatformWindow(window)
      +     , mDisplay(display)
      +-    , mFrameQueue(mDisplay->createFrameQueue())
      +     , mResizeAfterSwap(qEnvironmentVariableIsSet("QT_WAYLAND_RESIZE_AFTER_SWAP"))
      + {
      +     {
      +@@ -95,9 +94,6 @@ QWaylandWindow::QWaylandWindow(QWindow *window, QWaylandDisplay *display)
      + 
      + QWaylandWindow::~QWaylandWindow()
      + {
      +-    mDisplay->destroyFrameQueue(mFrameQueue);
      +-    mDisplay->handleWindowDestroyed(this);
      +-
      +     delete mWindowDecoration;
      + 
      +     if (mSurface)
      +@@ -243,6 +239,7 @@ bool QWaylandWindow::shouldCreateSubSurface() const
      + 
      + void QWaylandWindow::reset()
      + {
      ++    closeChildPopups();
      +     delete mShellSurface;
      +     mShellSurface = nullptr;
      +     delete mSubSurfaceWindow;
      +@@ -255,17 +252,22 @@ void QWaylandWindow::reset()
      +         mSurface.reset();
      +     }
      + 
      +-    if (mFrameCallback) {
      +-        wl_callback_destroy(mFrameCallback);
      +-        mFrameCallback = nullptr;
      +-    }
      ++    {
      ++        QMutexLocker lock(&mFrameSyncMutex);
      ++        if (mFrameCallback) {
      ++            wl_callback_destroy(mFrameCallback);
      ++            mFrameCallback = nullptr;
      ++        }
      + 
      +-    mFrameCallbackElapsedTimer.invalidate();
      +-    mWaitingForFrameCallback = false;
      ++        mFrameCallbackElapsedTimer.invalidate();
      ++        mWaitingForFrameCallback = false;
      ++    }
      +     mFrameCallbackTimedOut = false;
      + 
      +     mMask = QRegion();
      +     mQueuedBuffer = nullptr;
      ++
      ++    mDisplay->handleWindowDestroyed(this);
      + }
      + 
      + QWaylandWindow *QWaylandWindow::fromWlSurface(::wl_surface *surface)
      +@@ -351,19 +353,25 @@ void QWaylandWindow::setGeometry_helper(const QRect &rect)
      +     }
      + }
      + 
      +-void QWaylandWindow::setGeometry(const QRect &rect)
      ++void QWaylandWindow::setGeometry(const QRect &r)
      + {
      ++    auto rect = r;
      ++    if (fixedToplevelPositions && !QPlatformWindow::parent() && window()->type() != Qt::Popup
      ++        && window()->type() != Qt::ToolTip) {
      ++        rect.moveTo(screen()->geometry().topLeft());
      ++    }
      +     setGeometry_helper(rect);
      + 
      +     if (window()->isVisible() && rect.isValid()) {
      +         if (mWindowDecoration)
      +             mWindowDecoration->update();
      + 
      +-        if (mResizeAfterSwap && windowType() == Egl && mSentInitialResize)
      ++        if (mResizeAfterSwap && windowType() == Egl && mSentInitialResize) {
      ++            QMutexLocker lock(&mResizeLock);
      +             mResizeDirty = true;
      +-        else
      ++        } else {
      +             QWindowSystemInterface::handleGeometryChange(window(), geometry());
      +-
      ++        }
      +         mSentInitialResize = true;
      +     }
      +     QRect exposeGeometry(QPoint(), geometry().size());
      +@@ -374,7 +382,7 @@ void QWaylandWindow::setGeometry(const QRect &rect)
      +         mShellSurface->setWindowGeometry(windowContentGeometry());
      + 
      +     if (isOpaque() && mMask.isEmpty())
      +-        setOpaqueArea(rect);
      ++        setOpaqueArea(QRect(QPoint(0, 0), rect.size()));
      + }
      + 
      + void QWaylandWindow::resizeFromApplyConfigure(const QSize &sizeWithMargins, const QPoint &offset)
      +@@ -399,21 +407,6 @@ void QWaylandWindow::sendExposeEvent(const QRect &rect)
      +     mLastExposeGeometry = rect;
      + }
      + 
      +-
      +-static QVector> activePopups;
      +-
      +-void QWaylandWindow::closePopups(QWaylandWindow *parent)
      +-{
      +-    while (!activePopups.isEmpty()) {
      +-        auto popup = activePopups.takeLast();
      +-        if (popup.isNull())
      +-            continue;
      +-        if (popup.data() == parent)
      +-            return;
      +-        popup->reset();
      +-    }
      +-}
      +-
      + QPlatformScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const
      + {
      +     QReadLocker lock(&mSurfaceLock);
      +@@ -433,10 +426,7 @@ void QWaylandWindow::setVisible(bool visible)
      +     lastVisible = visible;
      + 
      +     if (visible) {
      +-        if (window()->type() == Qt::Popup || window()->type() == Qt::ToolTip)
      +-            activePopups << this;
      +         initWindow();
      +-        mDisplay->flushRequests();
      + 
      +         setGeometry(windowGeometry());
      +         // Don't flush the events here, or else the newly visible window may start drawing, but since
      +@@ -444,7 +434,6 @@ void QWaylandWindow::setVisible(bool visible)
      +         // QWaylandShmBackingStore::beginPaint().
      +     } else {
      +         sendExposeEvent(QRect());
      +-        closePopups(this);
      +         reset();
      +     }
      + }
      +@@ -556,12 +545,12 @@ void QWaylandWindow::sendRecursiveExposeEvent()
      + 
      + void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y)
      + {
      +-    Q_ASSERT(!buffer->committed());
      +     QReadLocker locker(&mSurfaceLock);
      +     if (mSurface == nullptr)
      +         return;
      + 
      +     if (buffer) {
      ++        Q_ASSERT(!buffer->committed());
      +         handleUpdate();
      +         buffer->setBusy();
      + 
      +@@ -583,7 +572,11 @@ void QWaylandWindow::damage(const QRect &rect)
      +     if (mSurface == nullptr)
      +         return;
      + 
      +-    mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
      ++    const int s = scale();
      ++    if (mDisplay->compositorVersion() >= 4)
      ++        mSurface->damage_buffer(s * rect.x(), s * rect.y(), s * rect.width(), s * rect.height());
      ++    else
      ++        mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
      + }
      + 
      + void QWaylandWindow::safeCommit(QWaylandBuffer *buffer, const QRegion &damage)
      +@@ -619,8 +612,14 @@ void QWaylandWindow::commit(QWaylandBuffer *buffer, const QRegion &damage)
      +         return;
      + 
      +     attachOffset(buffer);
      +-    for (const QRect &rect: damage)
      +-        mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
      ++    if (mDisplay->compositorVersion() >= 4) {
      ++        const int s = scale();
      ++        for (const QRect &rect: damage)
      ++            mSurface->damage_buffer(s * rect.x(), s * rect.y(), s * rect.width(), s * rect.height());
      ++    } else {
      ++        for (const QRect &rect: damage)
      ++            mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
      ++    }
      +     Q_ASSERT(!buffer->committed());
      +     buffer->setCommitted();
      +     mSurface->commit();
      +@@ -635,42 +634,53 @@ void QWaylandWindow::commit()
      + 
      + const wl_callback_listener QWaylandWindow::callbackListener = {
      +     [](void *data, wl_callback *callback, uint32_t time) {
      +-        Q_UNUSED(callback);
      +         Q_UNUSED(time);
      +         auto *window = static_cast(data);
      +-        window->handleFrameCallback();
      ++        window->handleFrameCallback(callback);
      +     }
      + };
      + 
      +-void QWaylandWindow::handleFrameCallback()
      ++void QWaylandWindow::handleFrameCallback(wl_callback* callback)
      + {
      ++    QMutexLocker locker(&mFrameSyncMutex);
      ++    if (!mFrameCallback) {
      ++        // This means the callback is already unset by QWaylandWindow::reset.
      ++        // The wl_callback object will be destroyed there too.
      ++        return;
      ++    }
      ++    Q_ASSERT(callback == mFrameCallback);
      ++    wl_callback_destroy(callback);
      ++    mFrameCallback = nullptr;
      ++
      +     mWaitingForFrameCallback = false;
      +     mFrameCallbackElapsedTimer.invalidate();
      + 
      +     // The rest can wait until we can run it on the correct thread
      +-    if (!mWaitingForUpdateDelivery) {
      +-        auto doHandleExpose = [this]() {
      +-            bool wasExposed = isExposed();
      +-            mFrameCallbackTimedOut = false;
      +-            if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed?
      +-                sendExposeEvent(QRect(QPoint(), geometry().size()));
      +-            if (wasExposed && hasPendingUpdateRequest())
      +-                deliverUpdateRequest();
      +-
      +-            mWaitingForUpdateDelivery = false;
      +-        };
      ++    auto doHandleExpose = [this]() {
      ++        mWaitingForUpdateDelivery.storeRelease(false);
      ++        bool wasExposed = isExposed();
      ++        mFrameCallbackTimedOut = false;
      ++        if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed?
      ++            sendExposeEvent(QRect(QPoint(), geometry().size()));
      ++        if (wasExposed && hasPendingUpdateRequest())
      ++            deliverUpdateRequest();
      ++    };
      + 
      ++    if (mWaitingForUpdateDelivery.testAndSetAcquire(false, true)) {
      +         // Queued connection, to make sure we don't call handleUpdate() from inside waitForFrameSync()
      +         // in the single-threaded case.
      +-        mWaitingForUpdateDelivery = true;
      +         QMetaObject::invokeMethod(this, doHandleExpose, Qt::QueuedConnection);
      +     }
      ++
      ++    mFrameSyncWait.notify_all();
      + }
      + 
      + bool QWaylandWindow::waitForFrameSync(int timeout)
      + {
      +-    QMutexLocker locker(mFrameQueue.mutex);
      +-    mDisplay->dispatchQueueWhile(mFrameQueue.queue, [&]() { return mWaitingForFrameCallback; }, timeout);
      ++    QMutexLocker locker(&mFrameSyncMutex);
      ++
      ++    QDeadlineTimer deadline(timeout);
      ++    while (mWaitingForFrameCallback && mFrameSyncWait.wait(&mFrameSyncMutex, deadline)) { }
      + 
      +     if (mWaitingForFrameCallback) {
      +         qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
      +@@ -868,6 +878,17 @@ bool QWaylandWindow::createDecoration()
      +             subsurf->set_position(pos.x() + m.left(), pos.y() + m.top());
      +         }
      +         sendExposeEvent(QRect(QPoint(), geometry().size()));
      ++
      ++        // This is a special case where the buffer is recreated, but since
      ++        // the content rect remains the same, the widgets remain the same
      ++        // size and are not redrawn, leaving the new buffer empty. As a simple
      ++        // work-around, we trigger a full extra update whenever the client-side
      ++        // window decorations are toggled while the window is showing.
      ++        // Note: createDecoration() is sometimes called from the render thread
      ++        // of Qt Quick. This is essentially wrong and could potentially cause problems,
      ++        // but until the underlying issue has been fixed, we have to use invokeMethod()
      ++        // here to avoid asserts.
      ++        QMetaObject::invokeMethod(window(), &QWindow::requestUpdate);
      +     }
      + 
      +     return mWindowDecoration;
      +@@ -1023,6 +1044,13 @@ void QWaylandWindow::handleScreensChanged()
      + 
      +     QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
      +     mLastReportedScreen = newScreen;
      ++    if (fixedToplevelPositions && !QPlatformWindow::parent() && window()->type() != Qt::Popup
      ++        && window()->type() != Qt::ToolTip
      ++        && geometry().topLeft() != newScreen->geometry().topLeft()) {
      ++        auto geometry = this->geometry();
      ++        geometry.moveTo(newScreen->geometry().topLeft());
      ++        setGeometry(geometry);
      ++    }
      + 
      +     int scale = newScreen->isPlaceholder() ? 1 : static_cast(newScreen)->scale();
      +     if (scale != mScale) {
      +@@ -1094,10 +1122,18 @@ bool QWaylandWindow::setMouseGrabEnabled(bool grab)
      +     return true;
      + }
      + 
      ++Qt::WindowStates QWaylandWindow::windowStates() const
      ++{
      ++    return mLastReportedWindowStates;
      ++}
      ++
      + void QWaylandWindow::handleWindowStatesChanged(Qt::WindowStates states)
      + {
      +     createDecoration();
      +-    QWindowSystemInterface::handleWindowStateChanged(window(), states, mLastReportedWindowStates);
      ++    Qt::WindowStates statesWithoutActive = states & ~Qt::WindowActive;
      ++    Qt::WindowStates lastStatesWithoutActive = mLastReportedWindowStates & ~Qt::WindowActive;
      ++    QWindowSystemInterface::handleWindowStateChanged(window(), statesWithoutActive,
      ++                                                     lastStatesWithoutActive);
      +     mLastReportedWindowStates = states;
      + }
      + 
      +@@ -1139,19 +1175,24 @@ void QWaylandWindow::timerEvent(QTimerEvent *event)
      +     if (event->timerId() != mFrameCallbackCheckIntervalTimerId)
      +         return;
      + 
      +-    bool callbackTimerExpired = mFrameCallbackElapsedTimer.hasExpired(mFrameCallbackTimeout);
      +-    if (!mFrameCallbackElapsedTimer.isValid() || callbackTimerExpired ) {
      +-        killTimer(mFrameCallbackCheckIntervalTimerId);
      +-        mFrameCallbackCheckIntervalTimerId = -1;
      +-    }
      +-    if (mFrameCallbackElapsedTimer.isValid() && callbackTimerExpired) {
      +-        mFrameCallbackElapsedTimer.invalidate();
      ++    {
      ++        QMutexLocker lock(&mFrameSyncMutex);
      + 
      +-        qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
      +-        mFrameCallbackTimedOut = true;
      +-        mWaitingForUpdate = false;
      +-        sendExposeEvent(QRect());
      ++        bool callbackTimerExpired = mFrameCallbackElapsedTimer.hasExpired(mFrameCallbackTimeout);
      ++        if (!mFrameCallbackElapsedTimer.isValid() || callbackTimerExpired ) {
      ++            killTimer(mFrameCallbackCheckIntervalTimerId);
      ++            mFrameCallbackCheckIntervalTimerId = -1;
      ++        }
      ++        if (!mFrameCallbackElapsedTimer.isValid() || !callbackTimerExpired) {
      ++            return;
      ++        }
      ++        mFrameCallbackElapsedTimer.invalidate();
      +     }
      ++
      ++    qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
      ++    mFrameCallbackTimedOut = true;
      ++    mWaitingForUpdate = false;
      ++    sendExposeEvent(QRect());
      + }
      + 
      + void QWaylandWindow::requestUpdate()
      +@@ -1160,8 +1201,11 @@ void QWaylandWindow::requestUpdate()
      +     Q_ASSERT(hasPendingUpdateRequest()); // should be set by QPA
      + 
      +     // If we have a frame callback all is good and will be taken care of there
      +-    if (mWaitingForFrameCallback)
      +-        return;
      ++    {
      ++        QMutexLocker locker(&mFrameSyncMutex);
      ++        if (mWaitingForFrameCallback)
      ++            return;
      ++    }
      + 
      +     // If we've already called deliverUpdateRequest(), but haven't seen any attach+commit/swap yet
      +     // This is a somewhat redundant behavior and might indicate a bug in the calling code, so log
      +@@ -1174,7 +1218,12 @@ void QWaylandWindow::requestUpdate()
      +     // so use invokeMethod to delay the delivery a bit.
      +     QMetaObject::invokeMethod(this, [this] {
      +         // Things might have changed in the meantime
      +-        if (hasPendingUpdateRequest() && !mWaitingForFrameCallback)
      ++        {
      ++            QMutexLocker locker(&mFrameSyncMutex);
      ++            if (mWaitingForFrameCallback)
      ++                return;
      ++        }
      ++        if (hasPendingUpdateRequest())
      +             deliverUpdateRequest();
      +     }, Qt::QueuedConnection);
      + }
      +@@ -1185,19 +1234,18 @@ void QWaylandWindow::requestUpdate()
      + void QWaylandWindow::handleUpdate()
      + {
      +     qCDebug(lcWaylandBackingstore) << "handleUpdate" << QThread::currentThread();
      ++
      +     // TODO: Should sync subsurfaces avoid requesting frame callbacks?
      +     QReadLocker lock(&mSurfaceLock);
      +     if (!mSurface)
      +         return;
      + 
      +-    if (mFrameCallback) {
      +-        wl_callback_destroy(mFrameCallback);
      +-        mFrameCallback = nullptr;
      +-    }
      ++    QMutexLocker locker(&mFrameSyncMutex);
      ++    if (mWaitingForFrameCallback)
      ++        return;
      + 
      +-    QMutexLocker locker(mFrameQueue.mutex);
      +     struct ::wl_surface *wrappedSurface = reinterpret_cast(wl_proxy_create_wrapper(mSurface->object()));
      +-    wl_proxy_set_queue(reinterpret_cast(wrappedSurface), mFrameQueue.queue);
      ++    wl_proxy_set_queue(reinterpret_cast(wrappedSurface), mDisplay->frameEventQueue());
      +     mFrameCallback = wl_surface_frame(wrappedSurface);
      +     wl_proxy_wrapper_destroy(wrappedSurface);
      +     wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this);
      +@@ -1207,6 +1255,8 @@ void QWaylandWindow::handleUpdate()
      +     // Start a timer for handling the case when the compositor stops sending frame callbacks.
      +     if (mFrameCallbackTimeout > 0) {
      +         QMetaObject::invokeMethod(this, [this] {
      ++            QMutexLocker locker(&mFrameSyncMutex);
      ++
      +             if (mWaitingForFrameCallback) {
      +                 if (mFrameCallbackCheckIntervalTimerId < 0)
      +                     mFrameCallbackCheckIntervalTimerId = startTimer(mFrameCallbackTimeout);
      +@@ -1267,6 +1317,20 @@ void QWaylandWindow::setOpaqueArea(const QRegion &opaqueArea)
      +     wl_region_destroy(region);
      + }
      + 
      ++void QWaylandWindow::addChildPopup(QWaylandWindow *surface) {
      ++    mChildPopups.append(surface);
      ++}
      ++
      ++void QWaylandWindow::removeChildPopup(QWaylandWindow *surface) {
      ++    mChildPopups.removeAll(surface);
      ++}
      ++
      ++void QWaylandWindow::closeChildPopups() {
      ++    while (!mChildPopups.isEmpty()) {
      ++        auto popup = mChildPopups.takeLast();
      ++        popup->reset();
      ++    }
      ++}
      + }
      + 
      + QT_END_NAMESPACE
      +diff --git a/qtwayland/src/client/qwaylandwindow_p.h b/qtwayland/src/client/qwaylandwindow_p.h
      +index 01337cff..2f219d8c 100644
      +--- a/qtwayland/src/client/qwaylandwindow_p.h
      ++++ b/qtwayland/src/client/qwaylandwindow_p.h
      +@@ -98,6 +98,9 @@ public:
      +     QWaylandWindow(QWindow *window, QWaylandDisplay *display);
      +     ~QWaylandWindow() override;
      + 
      ++    // Keep Toplevels position on the top left corner of their screen
      ++    static inline bool fixedToplevelPositions = true;
      ++
      +     virtual WindowType windowType() const = 0;
      +     virtual void ensureSize();
      +     WId winId() const override;
      +@@ -148,6 +151,7 @@ public:
      +     void setWindowState(Qt::WindowStates states) override;
      +     void setWindowFlags(Qt::WindowFlags flags) override;
      +     void handleWindowStatesChanged(Qt::WindowStates states);
      ++    Qt::WindowStates windowStates() const;
      + 
      +     void raise() override;
      +     void lower() override;
      +@@ -206,6 +210,10 @@ public:
      +     void handleUpdate();
      +     void deliverUpdateRequest() override;
      + 
      ++    void addChildPopup(QWaylandWindow* child);
      ++    void removeChildPopup(QWaylandWindow* child);
      ++    void closeChildPopups();
      ++
      + public slots:
      +     void applyConfigure();
      + 
      +@@ -215,7 +223,11 @@ signals:
      + 
      + protected:
      +     QWaylandDisplay *mDisplay = nullptr;
      ++
      ++    // mSurface can be written by the main thread. Other threads should claim a read lock for access
      ++    mutable QReadWriteLock mSurfaceLock;
      +     QScopedPointer mSurface;
      ++
      +     QWaylandShellSurface *mShellSurface = nullptr;
      +     QWaylandSubSurface *mSubSurfaceWindow = nullptr;
      +     QVector mChildren;
      +@@ -225,13 +237,14 @@ protected:
      +     Qt::MouseButtons mMousePressedInContentArea = Qt::NoButton;
      + 
      +     WId mWindowId;
      +-    bool mWaitingForFrameCallback = false;
      +     bool mFrameCallbackTimedOut = false; // Whether the frame callback has timed out
      +-    bool mWaitingForUpdateDelivery = false;
      +     int mFrameCallbackCheckIntervalTimerId = -1;
      +-    QElapsedTimer mFrameCallbackElapsedTimer;
      +-    struct ::wl_callback *mFrameCallback = nullptr;
      +-    QWaylandDisplay::FrameQueue mFrameQueue;
      ++    QAtomicInt mWaitingForUpdateDelivery = false;
      ++
      ++    bool mWaitingForFrameCallback = false; // Protected by mFrameSyncMutex
      ++    QElapsedTimer mFrameCallbackElapsedTimer; // Protected by mFrameSyncMutex
      ++    struct ::wl_callback *mFrameCallback = nullptr; // Protected by mFrameSyncMutex
      ++    QMutex mFrameSyncMutex;
      +     QWaitCondition mFrameSyncWait;
      + 
      +     // True when we have called deliverRequestUpdate, but the client has not yet attached a new buffer
      +@@ -261,6 +274,8 @@ protected:
      +     QWaylandBuffer *mQueuedBuffer = nullptr;
      +     QRegion mQueuedBufferDamage;
      + 
      ++    QList> mChildPopups;
      ++
      + private:
      +     void setGeometry_helper(const QRect &rect);
      +     void initWindow();
      +@@ -283,12 +298,10 @@ private:
      +     QRect mLastExposeGeometry;
      + 
      +     static const wl_callback_listener callbackListener;
      +-    void handleFrameCallback();
      ++    void handleFrameCallback(struct ::wl_callback* callback);
      + 
      +     static QWaylandWindow *mMouseGrab;
      + 
      +-    mutable QReadWriteLock mSurfaceLock;
      +-
      +     friend class QWaylandSubSurface;
      + };
      + 
      +diff --git a/qtwayland/src/client/shellintegration/qwaylandshellintegration_p.h b/qtwayland/src/client/shellintegration/qwaylandshellintegration_p.h
      +index ccad0048..4cc9b3b8 100644
      +--- a/qtwayland/src/client/shellintegration/qwaylandshellintegration_p.h
      ++++ b/qtwayland/src/client/shellintegration/qwaylandshellintegration_p.h
      +@@ -73,11 +73,10 @@ public:
      +         return true;
      +     }
      +     virtual QWaylandShellSurface *createShellSurface(QWaylandWindow *window) = 0;
      ++    // kept for binary compat with layer-shell-qt
      +     virtual void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) {
      +-        if (newFocus)
      +-            m_display->handleWindowActivated(newFocus);
      +-        if (oldFocus)
      +-            m_display->handleWindowDeactivated(oldFocus);
      ++        Q_UNUSED(newFocus);
      ++        Q_UNUSED(oldFocus);
      +     }
      +     virtual void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) {
      +         Q_UNUSED(resource);
      +diff --git a/qtwayland/src/compositor/configure.json b/qtwayland/src/compositor/configure.json
      +index bcfd5215..da95d07b 100644
      +--- a/qtwayland/src/compositor/configure.json
      ++++ b/qtwayland/src/compositor/configure.json
      +@@ -7,6 +7,31 @@
      +     "testDir": "../../config.tests",
      + 
      +     "libraries": {
      ++        "wayland-client": {
      ++            "label": "Wayland client library",
      ++            "headers": "wayland-version.h",
      ++            "test": {
      ++                "main": [
      ++                    "#if WAYLAND_VERSION_MAJOR < 1",
      ++                    "# error Wayland 1.8.0 or higher required",
      ++                    "#endif",
      ++                    "#if WAYLAND_VERSION_MAJOR == 1",
      ++                    "# if WAYLAND_VERSION_MINOR < 8",
      ++                    "#  error Wayland 1.8.0 or higher required",
      ++                    "# endif",
      ++                    "# if WAYLAND_VERSION_MINOR == 8",
      ++                    "#  if WAYLAND_VERSION_MICRO < 0",
      ++                    "#   error Wayland 1.8.0 or higher required",
      ++                    "#  endif",
      ++                    "# endif",
      ++                    "#endif"
      ++                 ]
      ++            },
      ++            "sources": [
      ++                { "type": "pkgConfig", "args": "wayland-client" },
      ++                "-lwayland-client"
      ++            ]
      ++        },
      +         "wayland-server": {
      +             "label": "wayland-server",
      +             "headers": "wayland-version.h",
      +@@ -151,8 +176,7 @@
      +                     "#endif"
      +                 ]
      +             },
      +-            "libs": "-ldrm",
      +-            "use": "egl"
      ++            "use": "drm egl"
      +         },
      +         "dmabuf-client-buffer": {
      +             "label": "Linux Client dma-buf Buffer Sharing",
      +@@ -176,8 +200,7 @@
      +                     "return 0;"
      +                 ]
      +             },
      +-            "libs": "-ldrm",
      +-            "use": "egl"
      ++            "use": "drm egl"
      +         },
      +         "vulkan-server-buffer": {
      +             "label": "Vulkan Buffer Sharing",
      +@@ -195,7 +218,8 @@
      +                     "exportAllocInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;",
      +                     "return 0;"
      +                 ]
      +-            }
      ++            },
      ++            "use": "wayland-client"
      +         }
      +     },
      + 
      +diff --git a/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp b/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp
      +index 7889f575..64140672 100644
      +--- a/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp
      ++++ b/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp
      +@@ -40,6 +40,7 @@
      + #include "qwaylandeglwindow.h"
      + 
      + #include 
      ++#include 
      + #include "qwaylandglcontext.h"
      + 
      + #include 
      +@@ -124,6 +125,7 @@ void QWaylandEglWindow::updateSurface(bool create)
      +         }
      +         mOffset = QPoint();
      +     } else {
      ++        QReadLocker locker(&mSurfaceLock);
      +         if (m_waylandEglWindow) {
      +             int current_width, current_height;
      +             static bool disableResizeCheck = qgetenv("QT_WAYLAND_DISABLE_RESIZECHECK").toInt();
      +@@ -131,14 +133,16 @@ void QWaylandEglWindow::updateSurface(bool create)
      +             if (!disableResizeCheck) {
      +                 wl_egl_window_get_attached_size(m_waylandEglWindow, ¤t_width, ¤t_height);
      +             }
      +-            if (disableResizeCheck || (current_width != sizeWithMargins.width() || current_height != sizeWithMargins.height())) {
      ++            if (disableResizeCheck || (current_width != sizeWithMargins.width() || current_height != sizeWithMargins.height()) || m_requestedSize != sizeWithMargins) {
      +                 wl_egl_window_resize(m_waylandEglWindow, sizeWithMargins.width(), sizeWithMargins.height(), mOffset.x(), mOffset.y());
      ++                m_requestedSize = sizeWithMargins;
      +                 mOffset = QPoint();
      + 
      +                 m_resize = true;
      +             }
      +-        } else if (create && wlSurface()) {
      +-            m_waylandEglWindow = wl_egl_window_create(wlSurface(), sizeWithMargins.width(), sizeWithMargins.height());
      ++        } else if (create && mSurface) {
      ++            m_waylandEglWindow = wl_egl_window_create(mSurface->object(), sizeWithMargins.width(), sizeWithMargins.height());
      ++            m_requestedSize = sizeWithMargins;
      +         }
      + 
      +         if (!m_eglSurface && m_waylandEglWindow && create) {
      +diff --git a/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h b/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h
      +index 5b1f4d56..0079dfef 100644
      +--- a/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h
      ++++ b/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h
      +@@ -88,6 +88,7 @@ private:
      +     mutable QOpenGLFramebufferObject *m_contentFBO = nullptr;
      + 
      +     QSurfaceFormat m_format;
      ++    QSize m_requestedSize;
      + };
      + 
      + }
      +diff --git a/qtwayland/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h b/qtwayland/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h
      +index 56a710c3..c6a8b6c6 100644
      +--- a/qtwayland/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h
      ++++ b/qtwayland/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h
      +@@ -41,6 +41,8 @@
      + #include 
      + #include 
      + 
      ++#include 
      ++
      + #include 
      + #include 
      + 
      +diff --git a/qtwayland/src/plugins/decorations/bradient/main.cpp b/qtwayland/src/plugins/decorations/bradient/main.cpp
      +index e75fda3c..fa885143 100644
      +--- a/qtwayland/src/plugins/decorations/bradient/main.cpp
      ++++ b/qtwayland/src/plugins/decorations/bradient/main.cpp
      +@@ -164,13 +164,10 @@ void QWaylandBradientDecoration::paint(QPaintDevice *device)
      +     // Window icon
      +     QIcon icon = waylandWindow()->windowIcon();
      +     if (!icon.isNull()) {
      +-        QPixmap pixmap = icon.pixmap(QSize(128, 128));
      +-        QPixmap scaled = pixmap.scaled(22, 22, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
      +-
      +         QRectF iconRect(0, 0, 22, 22);
      +-        p.drawPixmap(iconRect.adjusted(margins().left() + BUTTON_SPACING, 4,
      +-                                       margins().left() + BUTTON_SPACING, 4),
      +-                     scaled, iconRect);
      ++        iconRect.adjust(margins().left() + BUTTON_SPACING, 4,
      ++                        margins().left() + BUTTON_SPACING, 4),
      ++        icon.paint(&p, iconRect.toRect());
      +     }
      + 
      +     // Window title
      +diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5.cpp b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5.cpp
      +index 85d25e3c..60bdd491 100644
      +--- a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5.cpp
      ++++ b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5.cpp
      +@@ -47,18 +47,21 @@ QT_BEGIN_NAMESPACE
      + 
      + namespace QtWaylandClient {
      + 
      +-QWaylandXdgPopupV5::QWaylandXdgPopupV5(struct ::xdg_popup_v5 *popup, QWaylandWindow *window)
      ++QWaylandXdgPopupV5::QWaylandXdgPopupV5(struct ::xdg_popup_v5 *popup, QWaylandWindow* parent, QWaylandWindow *window)
      +     : QWaylandShellSurface(window)
      +     , QtWayland::xdg_popup_v5(popup)
      ++    , m_parent(parent)
      +     , m_window(window)
      + {
      +     if (window->display()->windowExtension())
      +         m_extendedWindow = new QWaylandExtendedSurface(window);
      ++    m_parent->addChildPopup(m_window);
      + }
      + 
      + QWaylandXdgPopupV5::~QWaylandXdgPopupV5()
      + {
      +     xdg_popup_destroy(object());
      ++    m_parent->removeChildPopup(m_window);
      +     delete m_extendedWindow;
      + }
      + 
      +diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5_p.h b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5_p.h
      +index 7494f6a6..d85f130b 100644
      +--- a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5_p.h
      ++++ b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5_p.h
      +@@ -70,7 +70,7 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandXdgPopupV5 : public QWaylandShellSurface
      + {
      +     Q_OBJECT
      + public:
      +-    QWaylandXdgPopupV5(struct ::xdg_popup_v5 *popup, QWaylandWindow *window);
      ++    QWaylandXdgPopupV5(struct ::xdg_popup_v5 *popup, QWaylandWindow* parent, QWaylandWindow *window);
      +     ~QWaylandXdgPopupV5() override;
      + 
      + protected:
      +@@ -78,6 +78,7 @@ protected:
      + 
      + private:
      +     QWaylandExtendedSurface *m_extendedWindow = nullptr;
      ++    QWaylandWindow *m_parent = nullptr;
      +     QWaylandWindow *m_window = nullptr;
      + };
      + 
      +diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp
      +index 7e242c4a..def8452a 100644
      +--- a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp
      ++++ b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp
      +@@ -84,7 +84,7 @@ QWaylandXdgPopupV5 *QWaylandXdgShellV5::createXdgPopup(QWaylandWindow *window, Q
      +     int x = position.x() + parentWindow->frameMargins().left();
      +     int y = position.y() + parentWindow->frameMargins().top();
      + 
      +-    auto popup = new QWaylandXdgPopupV5(get_xdg_popup(window->wlSurface(), parentSurface, seat, m_popupSerial, x, y), window);
      ++    auto popup = new QWaylandXdgPopupV5(get_xdg_popup(window->wlSurface(), parentSurface, seat, m_popupSerial, x, y), parentWindow, window);
      +     m_popups.append(window);
      +     QObject::connect(popup, &QWaylandXdgPopupV5::destroyed, [this, window](){
      +         m_popups.removeOne(window);
      +diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
      +index 4e25949f..cfc60939 100644
      +--- a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
      ++++ b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
      +@@ -85,13 +85,6 @@ QWaylandShellSurface *QWaylandXdgShellV5Integration::createShellSurface(QWayland
      +     return m_xdgShell->createXdgSurface(window);
      + }
      + 
      +-void QWaylandXdgShellV5Integration::handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) {
      +-    if (newFocus && qobject_cast(newFocus->shellSurface()))
      +-        m_display->handleWindowActivated(newFocus);
      +-    if (oldFocus && qobject_cast(oldFocus->shellSurface()))
      +-        m_display->handleWindowDeactivated(oldFocus);
      +-}
      +-
      + }
      + 
      + QT_END_NAMESPACE
      +diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration_p.h b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration_p.h
      +index ce6bdb9e..aed88670 100644
      +--- a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration_p.h
      ++++ b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration_p.h
      +@@ -67,7 +67,6 @@ public:
      +     QWaylandXdgShellV5Integration() {}
      +     bool initialize(QWaylandDisplay *display) override;
      +     QWaylandShellSurface *createShellSurface(QWaylandWindow *window) override;
      +-    void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) override;
      + 
      + private:
      +     QScopedPointer m_xdgShell;
      +diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6.cpp b/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6.cpp
      +index 8c371661..151c78e3 100644
      +--- a/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6.cpp
      ++++ b/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6.cpp
      +@@ -174,6 +174,7 @@ QWaylandXdgSurfaceV6::Popup::Popup(QWaylandXdgSurfaceV6 *xdgSurface, QWaylandXdg
      +     , m_xdgSurface(xdgSurface)
      +     , m_parent(parent)
      + {
      ++    m_parent->window()->addChildPopup(m_xdgSurface->window());
      + }
      + 
      + QWaylandXdgSurfaceV6::Popup::~Popup()
      +@@ -181,6 +182,8 @@ QWaylandXdgSurfaceV6::Popup::~Popup()
      +     if (isInitialized())
      +         destroy();
      + 
      ++    m_parent->window()->removeChildPopup(m_xdgSurface->window());
      ++
      +     if (m_grabbing) {
      +         auto *shell = m_xdgSurface->m_shell;
      +         Q_ASSERT(shell->m_topmostGrabbingPopup == this);
      +diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp b/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp
      +index 03164316..e8da8ba1 100644
      +--- a/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp
      ++++ b/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp
      +@@ -68,20 +68,6 @@ QWaylandShellSurface *QWaylandXdgShellV6Integration::createShellSurface(QWayland
      +     return m_xdgShell->getXdgSurface(window);
      + }
      + 
      +-void QWaylandXdgShellV6Integration::handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus)
      +-{
      +-    if (newFocus) {
      +-        auto *xdgSurface = qobject_cast(newFocus->shellSurface());
      +-        if (xdgSurface && !xdgSurface->handlesActiveState())
      +-            m_display->handleWindowActivated(newFocus);
      +-    }
      +-    if (oldFocus && qobject_cast(oldFocus->shellSurface())) {
      +-        auto *xdgSurface = qobject_cast(oldFocus->shellSurface());
      +-        if (xdgSurface && !xdgSurface->handlesActiveState())
      +-            m_display->handleWindowDeactivated(oldFocus);
      +-    }
      +-}
      +-
      + }
      + 
      + QT_END_NAMESPACE
      +diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration_p.h b/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration_p.h
      +index 261f8cbb..c1bcd5c6 100644
      +--- a/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration_p.h
      ++++ b/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration_p.h
      +@@ -65,7 +65,6 @@ public:
      +     QWaylandXdgShellV6Integration() {}
      +     bool initialize(QWaylandDisplay *display) override;
      +     QWaylandShellSurface *createShellSurface(QWaylandWindow *window) override;
      +-    void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) override;
      + 
      + private:
      +     QScopedPointer m_xdgShell;
      +diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
      +index f3e3c330..fa6d5808 100644
      +--- a/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
      ++++ b/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
      +@@ -67,11 +67,6 @@ QWaylandXdgSurface::Toplevel::Toplevel(QWaylandXdgSurface *xdgSurface)
      + 
      + QWaylandXdgSurface::Toplevel::~Toplevel()
      + {
      +-    if (m_applied.states & Qt::WindowActive) {
      +-        QWaylandWindow *window = m_xdgSurface->window();
      +-        window->display()->handleWindowDeactivated(window);
      +-    }
      +-
      +     // The protocol spec requires that the decoration object is deleted before xdg_toplevel.
      +     delete m_decoration;
      +     m_decoration = nullptr;
      +@@ -85,16 +80,15 @@ void QWaylandXdgSurface::Toplevel::applyConfigure()
      +     if (!(m_applied.states & (Qt::WindowMaximized|Qt::WindowFullScreen)))
      +         m_normalSize = m_xdgSurface->m_window->windowFrameGeometry().size();
      + 
      +-    if ((m_pending.states & Qt::WindowActive) && !(m_applied.states & Qt::WindowActive))
      ++    if ((m_pending.states & Qt::WindowActive) && !(m_applied.states & Qt::WindowActive)
      ++        && !m_xdgSurface->m_window->display()->isKeyboardAvailable())
      +         m_xdgSurface->m_window->display()->handleWindowActivated(m_xdgSurface->m_window);
      + 
      +-    if (!(m_pending.states & Qt::WindowActive) && (m_applied.states & Qt::WindowActive))
      ++    if (!(m_pending.states & Qt::WindowActive) && (m_applied.states & Qt::WindowActive)
      ++        && !m_xdgSurface->m_window->display()->isKeyboardAvailable())
      +         m_xdgSurface->m_window->display()->handleWindowDeactivated(m_xdgSurface->m_window);
      + 
      +-    // TODO: none of the other plugins send WindowActive either, but is it on purpose?
      +-    Qt::WindowStates statesWithoutActive = m_pending.states & ~Qt::WindowActive;
      +-
      +-    m_xdgSurface->m_window->handleWindowStatesChanged(statesWithoutActive);
      ++    m_xdgSurface->m_window->handleWindowStatesChanged(m_pending.states);
      + 
      +     if (m_pending.size.isEmpty()) {
      +         // An empty size in the configure means it's up to the client to choose the size
      +@@ -105,8 +99,6 @@ void QWaylandXdgSurface::Toplevel::applyConfigure()
      +         m_xdgSurface->m_window->resizeFromApplyConfigure(m_pending.size);
      +     }
      + 
      +-    m_xdgSurface->setSizeHints();
      +-
      +     m_applied = m_pending;
      +     qCDebug(lcQpaWayland) << "Applied pending xdg_toplevel configure event:" << m_applied.size << m_applied.states;
      + }
      +@@ -203,12 +195,17 @@ QtWayland::xdg_toplevel::resize_edge QWaylandXdgSurface::Toplevel::convertToResi
      +                 | ((edges & Qt::RightEdge) ? resize_edge_right : 0));
      + }
      + 
      +-QWaylandXdgSurface::Popup::Popup(QWaylandXdgSurface *xdgSurface, QWaylandXdgSurface *parent,
      ++QWaylandXdgSurface::Popup::Popup(QWaylandXdgSurface *xdgSurface, QWaylandWindow *parent,
      +                                  QtWayland::xdg_positioner *positioner)
      +-    : xdg_popup(xdgSurface->get_popup(parent->object(), positioner->object()))
      +-    , m_xdgSurface(xdgSurface)
      ++    : m_xdgSurface(xdgSurface)
      ++    , m_parentXdgSurface(qobject_cast(parent->shellSurface()))
      +     , m_parent(parent)
      + {
      ++
      ++    init(xdgSurface->get_popup(m_parentXdgSurface ? m_parentXdgSurface->object() : nullptr, positioner->object()));
      ++    if (m_parent) {
      ++        m_parent->addChildPopup(m_xdgSurface->window());
      ++    }
      + }
      + 
      + QWaylandXdgSurface::Popup::~Popup()
      +@@ -216,10 +213,24 @@ QWaylandXdgSurface::Popup::~Popup()
      +     if (isInitialized())
      +         destroy();
      + 
      ++    if (m_parent) {
      ++        m_parent->removeChildPopup(m_xdgSurface->window());
      ++    }
      ++
      +     if (m_grabbing) {
      +         auto *shell = m_xdgSurface->m_shell;
      +         Q_ASSERT(shell->m_topmostGrabbingPopup == this);
      +-        shell->m_topmostGrabbingPopup = m_parent->m_popup;
      ++        shell->m_topmostGrabbingPopup = m_parentXdgSurface ? m_parentXdgSurface->m_popup : nullptr;
      ++        m_grabbing = false;
      ++
      ++        // Synthesize Qt enter/leave events for popup
      ++        QWindow *leave = nullptr;
      ++        if (m_xdgSurface && m_xdgSurface->window())
      ++            leave = m_xdgSurface->window()->window();
      ++        QWindowSystemInterface::handleLeaveEvent(leave);
      ++
      ++        if (QWindow *enter = QGuiApplication::topLevelAt(QCursor::pos()))
      ++            QWindowSystemInterface::handleEnterEvent(enter, enter->mapFromGlobal(QCursor::pos()), QCursor::pos());
      +     }
      + }
      + 
      +@@ -257,6 +268,7 @@ QWaylandXdgSurface::QWaylandXdgSurface(QWaylandXdgShell *shell, ::xdg_surface *s
      +                 m_toplevel->set_parent(parentXdgSurface->m_toplevel->object());
      +         }
      +     }
      ++    setSizeHints();
      + }
      + 
      + QWaylandXdgSurface::~QWaylandXdgSurface()
      +@@ -400,8 +412,6 @@ void QWaylandXdgSurface::setPopup(QWaylandWindow *parent)
      + {
      +     Q_ASSERT(!m_toplevel && !m_popup);
      + 
      +-    auto parentXdgSurface = static_cast(parent->shellSurface());
      +-
      +     auto positioner = new QtWayland::xdg_positioner(m_shell->create_positioner());
      +     // set_popup expects a position relative to the parent
      +     QPoint transientPos = m_window->geometry().topLeft(); // this is absolute
      +@@ -414,8 +424,9 @@ void QWaylandXdgSurface::setPopup(QWaylandWindow *parent)
      +     positioner->set_anchor(QtWayland::xdg_positioner::anchor_top_left);
      +     positioner->set_gravity(QtWayland::xdg_positioner::gravity_bottom_right);
      +     positioner->set_size(m_window->geometry().width(), m_window->geometry().height());
      +-    m_popup = new Popup(this, parentXdgSurface, positioner);
      ++    m_popup = new Popup(this, parent, positioner);
      +     positioner->destroy();
      ++
      +     delete positioner;
      + }
      + 
      +@@ -437,6 +448,23 @@ void QWaylandXdgSurface::setGrabPopup(QWaylandWindow *parent, QWaylandInputDevic
      +     }
      +     setPopup(parent);
      +     m_popup->grab(device, serial);
      ++
      ++    // Synthesize Qt enter/leave events for popup
      ++    if (!parent)
      ++        return;
      ++    QWindow *current = QGuiApplication::topLevelAt(QCursor::pos());
      ++    QWindow *leave = parent->window();
      ++    if (current != leave)
      ++        return;
      ++
      ++    QWindowSystemInterface::handleLeaveEvent(leave);
      ++
      ++    QWindow *enter = nullptr;
      ++    if (m_popup && m_popup->m_xdgSurface && m_popup->m_xdgSurface->window())
      ++        enter = m_popup->m_xdgSurface->window()->window();
      ++
      ++    if (enter)
      ++        QWindowSystemInterface::handleEnterEvent(enter, enter->mapFromGlobal(QCursor::pos()), QCursor::pos());
      + }
      + 
      + void QWaylandXdgSurface::xdg_surface_configure(uint32_t serial)
      +diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h b/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
      +index 96785205..4b518f0a 100644
      +--- a/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
      ++++ b/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
      +@@ -131,14 +131,15 @@ private:
      + 
      +     class Popup : public QtWayland::xdg_popup {
      +     public:
      +-        Popup(QWaylandXdgSurface *xdgSurface, QWaylandXdgSurface *parent, QtWayland::xdg_positioner *positioner);
      ++        Popup(QWaylandXdgSurface *xdgSurface, QWaylandWindow *parent, QtWayland::xdg_positioner *positioner);
      +         ~Popup() override;
      + 
      +         void grab(QWaylandInputDevice *seat, uint serial);
      +         void xdg_popup_popup_done() override;
      + 
      +         QWaylandXdgSurface *m_xdgSurface = nullptr;
      +-        QWaylandXdgSurface *m_parent = nullptr;
      ++        QWaylandXdgSurface *m_parentXdgSurface = nullptr;
      ++        QWaylandWindow *m_parent = nullptr;
      +         bool m_grabbing = false;
      +     };
      + 
      +diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp b/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp
      +index 8769d971..da0dd6a7 100644
      +--- a/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp
      ++++ b/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp
      +@@ -69,20 +69,6 @@ QWaylandShellSurface *QWaylandXdgShellIntegration::createShellSurface(QWaylandWi
      +     return m_xdgShell->getXdgSurface(window);
      + }
      + 
      +-void QWaylandXdgShellIntegration::handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus)
      +-{
      +-    if (newFocus) {
      +-        auto *xdgSurface = qobject_cast(newFocus->shellSurface());
      +-        if (xdgSurface && !xdgSurface->handlesActiveState())
      +-            m_display->handleWindowActivated(newFocus);
      +-    }
      +-    if (oldFocus && qobject_cast(oldFocus->shellSurface())) {
      +-        auto *xdgSurface = qobject_cast(oldFocus->shellSurface());
      +-        if (xdgSurface && !xdgSurface->handlesActiveState())
      +-            m_display->handleWindowDeactivated(oldFocus);
      +-    }
      +-}
      +-
      + }
      + 
      + QT_END_NAMESPACE
      +diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h b/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h
      +index b6caa6c9..2f929f98 100644
      +--- a/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h
      ++++ b/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h
      +@@ -65,7 +65,6 @@ public:
      +     QWaylandXdgShellIntegration() {}
      +     bool initialize(QWaylandDisplay *display) override;
      +     QWaylandShellSurface *createShellSurface(QWaylandWindow *window) override;
      +-    void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) override;
      + 
      + private:
      +     QScopedPointer m_xdgShell;
      +diff --git a/qtwayland/src/shared/qwaylandinputmethodeventbuilder.cpp b/qtwayland/src/shared/qwaylandinputmethodeventbuilder.cpp
      +index 526d0ef4..f50ccf30 100644
      +--- a/qtwayland/src/shared/qwaylandinputmethodeventbuilder.cpp
      ++++ b/qtwayland/src/shared/qwaylandinputmethodeventbuilder.cpp
      +@@ -39,7 +39,10 @@
      + 
      + #include "qwaylandinputmethodeventbuilder_p.h"
      + 
      ++#include 
      ++#include 
      + #include 
      ++#include 
      + #include 
      + 
      + #ifdef QT_BUILD_WAYLANDCOMPOSITOR_LIB
      +@@ -81,32 +84,38 @@ void QWaylandInputMethodEventBuilder::addPreeditStyling(uint32_t index, uint32_t
      +     QTextCharFormat format;
      + 
      +     switch (style) {
      +-    case 0:
      +-    case 1:
      ++    case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_NONE:
      ++        break;
      ++    case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_DEFAULT:
      ++    case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_UNDERLINE:
      +         format.setFontUnderline(true);
      +         format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
      +         m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
      +         break;
      +-    case 2:
      +-    case 3:
      ++    case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_ACTIVE:
      ++    case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_INACTIVE:
      +         format.setFontWeight(QFont::Bold);
      +         format.setFontUnderline(true);
      +         format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
      +         m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
      +         break;
      +-    case 4:
      +-        format.setFontUnderline(true);
      +-        format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
      +-        m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
      ++    case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_HIGHLIGHT:
      ++    case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_SELECTION:
      ++        {
      ++            format.setFontUnderline(true);
      ++            format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
      ++            QPalette palette = qApp->palette();
      ++            format.setBackground(QBrush(palette.color(QPalette::Active, QPalette::Highlight)));
      ++            format.setForeground(QBrush(palette.color(QPalette::Active, QPalette::HighlightedText)));
      ++            m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
      ++        }
      +         break;
      +-    case 5:
      ++    case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_INCORRECT:
      +         format.setFontUnderline(true);
      +         format.setUnderlineStyle(QTextCharFormat::WaveUnderline);
      +         format.setUnderlineColor(QColor(Qt::red));
      +         m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
      +         break;
      +-//    case QtWayland::wl_text_input::preedit_style_selection:
      +-//    case QtWayland::wl_text_input::preedit_style_none:
      +     default:
      +         break;
      +     }
      +@@ -153,7 +162,7 @@ QInputMethodEvent QWaylandInputMethodEventBuilder::buildPreedit(const QString &t
      + 
      +     if (m_preeditCursor < 0) {
      +         attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant()));
      +-    } else if (m_preeditCursor > 0) {
      ++    } else {
      +         attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, indexFromWayland(text, m_preeditCursor), 1, QVariant()));
      +     }
      + 
      +diff --git a/qtwayland/src/shared/qwaylandmimehelper.cpp b/qtwayland/src/shared/qwaylandmimehelper.cpp
      +index a5fdd34d..e2fe1928 100644
      +--- a/qtwayland/src/shared/qwaylandmimehelper.cpp
      ++++ b/qtwayland/src/shared/qwaylandmimehelper.cpp
      +@@ -60,7 +60,7 @@ QByteArray QWaylandMimeHelper::getByteArray(QMimeData *mimeData, const QString &
      +             buf.open(QIODevice::ReadWrite);
      +             QByteArray fmt = "BMP";
      +             if (mimeType.startsWith(QLatin1String("image/"))) {
      +-                QByteArray imgFmt = mimeType.mid(6).toUpper().toLatin1();
      ++                QByteArray imgFmt = mimeType.mid(6).toLower().toLatin1();
      +                 if (QImageWriter::supportedImageFormats().contains(imgFmt))
      +                     fmt = imgFmt;
      +             }
      +@@ -74,7 +74,7 @@ QByteArray QWaylandMimeHelper::getByteArray(QMimeData *mimeData, const QString &
      +         QList urls = mimeData->urls();
      +         for (int i = 0; i < urls.count(); ++i) {
      +             content.append(urls.at(i).toEncoded());
      +-            content.append('\n');
      ++            content.append("\r\n");
      +         }
      +     } else {
      +         content = mimeData->data(mimeType);
      +diff --git a/qtwayland/tests/auto/client/datadevicev1/tst_datadevicev1.cpp b/qtwayland/tests/auto/client/datadevicev1/tst_datadevicev1.cpp
      +index 1568b3b9..067410d0 100644
      +--- a/qtwayland/tests/auto/client/datadevicev1/tst_datadevicev1.cpp
      ++++ b/qtwayland/tests/auto/client/datadevicev1/tst_datadevicev1.cpp
      +@@ -35,7 +35,7 @@
      + 
      + using namespace MockCompositor;
      + 
      +-constexpr int dataDeviceVersion = 1;
      ++constexpr int dataDeviceVersion = 3;
      + 
      + class DataDeviceCompositor : public DefaultCompositor {
      + public:
      +diff --git a/qtwayland/tests/auto/client/seatv5/tst_seatv5.cpp b/qtwayland/tests/auto/client/seatv5/tst_seatv5.cpp
      +index 9312c2e5..2ea382f1 100644
      +--- a/qtwayland/tests/auto/client/seatv5/tst_seatv5.cpp
      ++++ b/qtwayland/tests/auto/client/seatv5/tst_seatv5.cpp
      +@@ -73,6 +73,7 @@ private slots:
      +     void multiTouch();
      +     void multiTouchUpAndMotionFrame();
      +     void tapAndMoveInSameFrame();
      ++    void cancelTouch();
      + };
      + 
      + void tst_seatv5::bindsToSeat()
      +@@ -646,5 +647,34 @@ void tst_seatv5::tapAndMoveInSameFrame()
      +     QTRY_COMPARE(window.m_events.last().touchPoints.first().state(), Qt::TouchPointState::TouchPointReleased);
      + }
      + 
      ++void tst_seatv5::cancelTouch()
      ++{
      ++    TouchWindow window;
      ++    QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial);
      ++
      ++    exec([=] {
      ++        auto *t = touch();
      ++        auto *c = client();
      ++        t->sendDown(xdgToplevel()->surface(), {32, 32}, 1);
      ++        t->sendFrame(c);
      ++        t->sendCancel(c);
      ++        t->sendFrame(c);
      ++    });
      ++
      ++    QTRY_VERIFY(!window.m_events.empty());
      ++    {
      ++        auto e = window.m_events.takeFirst();
      ++        QCOMPARE(e.type, QEvent::TouchBegin);
      ++        QCOMPARE(e.touchPointStates, Qt::TouchPointPressed);
      ++        QCOMPARE(e.touchPoints.length(), 1);
      ++        QCOMPARE(e.touchPoints.first().pos(), QPointF(32-window.frameMargins().left(), 32-window.frameMargins().top()));
      ++    }
      ++    {
      ++        auto e = window.m_events.takeFirst();
      ++        QCOMPARE(e.type, QEvent::TouchCancel);
      ++        QCOMPARE(e.touchPoints.length(), 0);
      ++    }
      ++}
      ++
      + QCOMPOSITOR_TEST_MAIN(tst_seatv5)
      + #include "tst_seatv5.moc"
      +diff --git a/qtwayland/tests/auto/client/shared/corecompositor.cpp b/qtwayland/tests/auto/client/shared/corecompositor.cpp
      +index 5c6c83ba..fa9b7662 100644
      +--- a/qtwayland/tests/auto/client/shared/corecompositor.cpp
      ++++ b/qtwayland/tests/auto/client/shared/corecompositor.cpp
      +@@ -27,6 +27,7 @@
      + ****************************************************************************/
      + 
      + #include "corecompositor.h"
      ++#include 
      + 
      + namespace MockCompositor {
      + 
      +diff --git a/qtwayland/tests/auto/client/shared/coreprotocol.cpp b/qtwayland/tests/auto/client/shared/coreprotocol.cpp
      +index 0d988521..d1a2e7cb 100644
      +--- a/qtwayland/tests/auto/client/shared/coreprotocol.cpp
      ++++ b/qtwayland/tests/auto/client/shared/coreprotocol.cpp
      +@@ -451,6 +451,13 @@ void Touch::sendFrame(wl_client *client)
      +         send_frame(r->handle);
      + }
      + 
      ++void Touch::sendCancel(wl_client *client)
      ++{
      ++    const auto touchResources = resourceMap().values(client);
      ++    for (auto *r : touchResources)
      ++        send_cancel(r->handle);
      ++}
      ++
      + uint Keyboard::sendEnter(Surface *surface)
      + {
      +     auto serial = m_seat->m_compositor->nextSerial();
      +diff --git a/qtwayland/tests/auto/client/shared/coreprotocol.h b/qtwayland/tests/auto/client/shared/coreprotocol.h
      +index a1af137a..210d8ddb 100644
      +--- a/qtwayland/tests/auto/client/shared/coreprotocol.h
      ++++ b/qtwayland/tests/auto/client/shared/coreprotocol.h
      +@@ -158,7 +158,7 @@ class WlCompositor : public Global, public QtWaylandServer::wl_compositor
      + {
      +     Q_OBJECT
      + public:
      +-    explicit WlCompositor(CoreCompositor *compositor, int version = 3)
      ++    explicit WlCompositor(CoreCompositor *compositor, int version = 4)
      +         : QtWaylandServer::wl_compositor(compositor->m_display, version)
      +         , m_compositor(compositor)
      +     {}
      +@@ -364,6 +364,7 @@ public:
      +     uint sendUp(wl_client *client, int id);
      +     void sendMotion(wl_client *client, const QPointF &position, int id);
      +     void sendFrame(wl_client *client);
      ++    void sendCancel(wl_client *client);
      + 
      +     Seat *m_seat = nullptr;
      + };
      +diff --git a/qtwayland/tests/auto/client/shared_old/mockcompositor.cpp b/qtwayland/tests/auto/client/shared_old/mockcompositor.cpp
      +index a415cbf5..b1d3d07d 100644
      +--- a/qtwayland/tests/auto/client/shared_old/mockcompositor.cpp
      ++++ b/qtwayland/tests/auto/client/shared_old/mockcompositor.cpp
      +@@ -342,7 +342,7 @@ Compositor::Compositor(MockCompositor *mockCompositor)
      +         exit(EXIT_FAILURE);
      +     }
      + 
      +-    wl_global_create(m_display, &wl_compositor_interface, 1, this, bindCompositor);
      ++    wl_global_create(m_display, &wl_compositor_interface, 4, this, bindCompositor);
      + 
      +     m_data_device_manager.reset(new DataDeviceManager(this, m_display));
      + 
      +diff --git a/qtwayland/tests/auto/client/shared_old/mocksurface.cpp b/qtwayland/tests/auto/client/shared_old/mocksurface.cpp
      +index e9df5f90..c3246e4a 100644
      +--- a/qtwayland/tests/auto/client/shared_old/mocksurface.cpp
      ++++ b/qtwayland/tests/auto/client/shared_old/mocksurface.cpp
      +@@ -125,6 +125,16 @@ void Surface::surface_damage(Resource *resource,
      +     Q_UNUSED(height);
      + }
      + 
      ++void Surface::surface_damage_buffer(Resource *resource,
      ++                                    int32_t x, int32_t y, int32_t width, int32_t height)
      ++{
      ++    Q_UNUSED(resource);
      ++    Q_UNUSED(x);
      ++    Q_UNUSED(y);
      ++    Q_UNUSED(width);
      ++    Q_UNUSED(height);
      ++}
      ++
      + void Surface::surface_frame(Resource *resource,
      +                             uint32_t callback)
      + {
      +diff --git a/qtwayland/tests/auto/client/shared_old/mocksurface.h b/qtwayland/tests/auto/client/shared_old/mocksurface.h
      +index 949dc23d..d176837e 100644
      +--- a/qtwayland/tests/auto/client/shared_old/mocksurface.h
      ++++ b/qtwayland/tests/auto/client/shared_old/mocksurface.h
      +@@ -65,6 +65,8 @@ protected:
      +                         struct wl_resource *buffer, int x, int y) override;
      +     void surface_damage(Resource *resource,
      +                         int32_t x, int32_t y, int32_t width, int32_t height) override;
      ++    void surface_damage_buffer(Resource *resource,
      ++                               int32_t x, int32_t y, int32_t width, int32_t height) override;
      +     void surface_frame(Resource *resource,
      +                        uint32_t callback) override;
      +     void surface_commit(Resource *resource) override;
      +diff --git a/qtwayland/tests/auto/client/surface/tst_surface.cpp b/qtwayland/tests/auto/client/surface/tst_surface.cpp
      +index 95e4e609..60c672ce 100644
      +--- a/qtwayland/tests/auto/client/surface/tst_surface.cpp
      ++++ b/qtwayland/tests/auto/client/surface/tst_surface.cpp
      +@@ -129,6 +129,10 @@ void tst_surface::waitForFrameCallbackGl()
      +     // Make sure we follow frame callbacks for some frames
      +     for (int i = 0; i < 5; ++i) {
      +         xdgPingAndWaitForPong(); // Make sure things have happened on the client
      ++        if (!qEnvironmentVariableIntValue("QT_WAYLAND_DISABLE_WINDOWDECORATION") && i == 0) {
      ++            QCOMPARE(bufferSpy.count(), 1);
      ++            bufferSpy.removeFirst();
      ++        }
      +         exec([&] {
      +             QVERIFY(bufferSpy.empty()); // Make sure no extra buffers have arrived
      +             QVERIFY(!xdgToplevel()->surface()->m_waitingFrameCallbacks.empty());
      +diff --git a/qtwayland/tests/auto/client/xdgshell/tst_xdgshell.cpp b/qtwayland/tests/auto/client/xdgshell/tst_xdgshell.cpp
      +index 2277bbb8..747875b4 100644
      +--- a/qtwayland/tests/auto/client/xdgshell/tst_xdgshell.cpp
      ++++ b/qtwayland/tests/auto/client/xdgshell/tst_xdgshell.cpp
      +@@ -31,6 +31,7 @@
      + #include 
      + #include 
      + #include 
      ++#include 
      + 
      + using namespace MockCompositor;
      + 
      +@@ -45,6 +46,7 @@ private slots:
      +     void configureStates();
      +     void popup();
      +     void tooltipOnPopup();
      ++    void tooltipAndSiblingPopup();
      +     void switchPopups();
      +     void hidePopupParent();
      +     void pongs();
      +@@ -138,6 +140,7 @@ void tst_xdgshell::configureSize()
      + 
      + void tst_xdgshell::configureStates()
      + {
      ++    QVERIFY(qputenv("QT_WAYLAND_FRAME_CALLBACK_TIMEOUT", "0"));
      +     QRasterWindow window;
      +     window.resize(64, 48);
      +     window.show();
      +@@ -154,9 +157,12 @@ void tst_xdgshell::configureStates()
      +     // Toplevel windows don't know their position on xdg-shell
      + //    QCOMPARE(window.frameGeometry().topLeft(), QPoint()); // TODO: this doesn't currently work when window decorations are enabled
      + 
      +-//    QEXPECT_FAIL("", "configure has already been acked, we shouldn't have to wait for isActive", Continue);
      +-//    QVERIFY(window.isActive());
      +-    QTRY_VERIFY(window.isActive()); // Just make sure it eventually get's set correctly
      ++    // window.windowstate() is driven by keyboard focus, however for decorations we want to follow
      ++    // XDGShell this is internal to QtWayland so it is queried directly
      ++    auto waylandWindow = static_cast(window.handle());
      ++    Q_ASSERT(waylandWindow);
      ++    QTRY_VERIFY(waylandWindow->windowStates().testFlag(
      ++            Qt::WindowActive)); // Just make sure it eventually get's set correctly
      + 
      +     const QSize screenSize(640, 480);
      +     const uint maximizedSerial = exec([=] {
      +@@ -186,6 +192,7 @@ void tst_xdgshell::configureStates()
      +     QCOMPARE(window.windowStates(), Qt::WindowNoState);
      +     QCOMPARE(window.frameGeometry().size(), windowedSize);
      + //    QCOMPARE(window.frameGeometry().topLeft(), QPoint()); // TODO: this doesn't currently work when window decorations are enabled
      ++    QVERIFY(qunsetenv("QT_WAYLAND_FRAME_CALLBACK_TIMEOUT"));
      + }
      + 
      + void tst_xdgshell::popup()
      +@@ -340,6 +347,92 @@ void tst_xdgshell::tooltipOnPopup()
      +     QCOMPOSITOR_TRY_COMPARE(xdgPopup(0), nullptr);
      + }
      + 
      ++void tst_xdgshell::tooltipAndSiblingPopup()
      ++{
      ++    class ToolTip : public QRasterWindow {
      ++    public:
      ++        explicit ToolTip(QWindow *parent) {
      ++            setTransientParent(parent);
      ++            setFlags(Qt::ToolTip);
      ++            resize(100, 100);
      ++            show();
      ++        }
      ++        void mousePressEvent(QMouseEvent *event) override {
      ++            QRasterWindow::mousePressEvent(event);
      ++            m_popup = new QRasterWindow;
      ++            m_popup->setTransientParent(transientParent());
      ++            m_popup->setFlags(Qt::Popup);
      ++            m_popup->resize(100, 100);
      ++            m_popup->show();
      ++        }
      ++
      ++        QRasterWindow *m_popup = nullptr;
      ++    };
      ++
      ++    class Window : public QRasterWindow {
      ++    public:
      ++        void mousePressEvent(QMouseEvent *event) override {
      ++            QRasterWindow::mousePressEvent(event);
      ++            m_tooltip = new ToolTip(this);
      ++        }
      ++        ToolTip *m_tooltip = nullptr;
      ++    };
      ++
      ++    Window window;
      ++    window.resize(200, 200);
      ++    window.show();
      ++
      ++    QCOMPOSITOR_TRY_VERIFY(xdgToplevel());
      ++    exec([=] { xdgToplevel()->sendCompleteConfigure(); });
      ++    QCOMPOSITOR_TRY_VERIFY(xdgToplevel()->m_xdgSurface->m_committedConfigureSerial);
      ++
      ++    exec([=] {
      ++        auto *surface = xdgToplevel()->surface();
      ++        auto *p = pointer();
      ++        auto *c = client();
      ++        p->sendEnter(surface, {100, 100});
      ++        p->sendFrame(c);
      ++        p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
      ++        p->sendButton(client(), BTN_LEFT, Pointer::button_state_released);
      ++        p->sendFrame(c);
      ++        p->sendLeave(surface);
      ++        p->sendFrame(c);
      ++    });
      ++
      ++    QCOMPOSITOR_TRY_VERIFY(xdgPopup());
      ++    exec([=] { xdgPopup()->sendCompleteConfigure(QRect(100, 100, 100, 100)); });
      ++    QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_xdgSurface->m_committedConfigureSerial);
      ++    QCOMPOSITOR_TRY_VERIFY(!xdgPopup()->m_grabbed);
      ++
      ++    exec([=] {
      ++        auto *surface = xdgPopup()->surface();
      ++        auto *p = pointer();
      ++        auto *c = client();
      ++        p->sendEnter(surface, {100, 100});
      ++        p->sendFrame(c);
      ++        p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
      ++        p->sendButton(client(), BTN_LEFT, Pointer::button_state_released);
      ++        p->sendFrame(c);
      ++    });
      ++
      ++    QCOMPOSITOR_TRY_VERIFY(xdgPopup(1));
      ++    exec([=] { xdgPopup(1)->sendCompleteConfigure(QRect(100, 100, 100, 100)); });
      ++    QCOMPOSITOR_TRY_VERIFY(xdgPopup(1)->m_xdgSurface->m_committedConfigureSerial);
      ++    QCOMPOSITOR_TRY_VERIFY(xdgPopup(1)->m_grabbed);
      ++
      ++    // Close the middle tooltip (it should not close the sibling popup)
      ++    window.m_tooltip->close();
      ++
      ++    QCOMPOSITOR_TRY_COMPARE(xdgPopup(1), nullptr);
      ++    // Verify the remaining xdg surface is a grab popup..
      ++    QCOMPOSITOR_TRY_VERIFY(xdgPopup(0));
      ++    QCOMPOSITOR_TRY_VERIFY(xdgPopup(0)->m_grabbed);
      ++
      ++    window.m_tooltip->m_popup->close();
      ++    QCOMPOSITOR_TRY_COMPARE(xdgPopup(1), nullptr);
      ++    QCOMPOSITOR_TRY_COMPARE(xdgPopup(0), nullptr);
      ++}
      ++
      + // QTBUG-65680
      + void tst_xdgshell::switchPopups()
      + {
      +@@ -505,7 +598,7 @@ void tst_xdgshell::minMaxSize()
      +     window.show();
      +     QCOMPOSITOR_TRY_VERIFY(xdgToplevel());
      + 
      +-    exec([=] { xdgToplevel()->sendCompleteConfigure(); });
      ++    // we don't roundtrip with our configuration the initial commit should be correct
      + 
      +     QCOMPOSITOR_TRY_COMPARE(xdgToplevel()->m_committed.minSize, QSize(100, 100));
      +     QCOMPOSITOR_TRY_COMPARE(xdgToplevel()->m_committed.maxSize, QSize(1000, 1000));
      +Submodule qtwebchannel 618422ee..f8949655:
      +diff --git a/qtwebchannel/src/webchannel/qmetaobjectpublisher.cpp b/qtwebchannel/src/webchannel/qmetaobjectpublisher.cpp
      +index 536eb5c..898d769 100644
      +--- a/qtwebchannel/src/webchannel/qmetaobjectpublisher.cpp
      ++++ b/qtwebchannel/src/webchannel/qmetaobjectpublisher.cpp
      +@@ -186,8 +186,6 @@ Q_DECLARE_TYPEINFO(OverloadResolutionCandidate, Q_MOVABLE_TYPE);
      + QMetaObjectPublisher::QMetaObjectPublisher(QWebChannel *webChannel)
      +     : QObject(webChannel)
      +     , webChannel(webChannel)
      +-    , signalHandler(this)
      +-    , clientIsIdle(false)
      +     , blockUpdates(false)
      +     , propertyUpdatesInitialized(false)
      + {
      +@@ -301,17 +299,17 @@ QJsonObject QMetaObjectPublisher::classInfoForObject(const QObject *object, QWeb
      +     return data;
      + }
      + 
      +-void QMetaObjectPublisher::setClientIsIdle(bool isIdle)
      ++void QMetaObjectPublisher::setClientIsIdle(bool isIdle, QWebChannelAbstractTransport *transport)
      + {
      +-    if (clientIsIdle == isIdle) {
      +-        return;
      +-    }
      +-    clientIsIdle = isIdle;
      +-    if (!isIdle && timer.isActive()) {
      +-        timer.stop();
      +-    } else if (isIdle && !timer.isActive()) {
      +-        timer.start(PROPERTY_UPDATE_INTERVAL, this);
      +-    }
      ++    transportState[transport].clientIsIdle = isIdle;
      ++    if (isIdle)
      ++        sendEnqueuedPropertyUpdates(transport);
      ++}
      ++
      ++bool QMetaObjectPublisher::isClientIdle(QWebChannelAbstractTransport *transport)
      ++{
      ++    auto found = transportState.find(transport);
      ++    return found != transportState.end() && found.value().clientIsIdle;
      + }
      + 
      + QJsonObject QMetaObjectPublisher::initializeClient(QWebChannelAbstractTransport *transport)
      +@@ -333,6 +331,7 @@ QJsonObject QMetaObjectPublisher::initializeClient(QWebChannelAbstractTransport
      + 
      + void QMetaObjectPublisher::initializePropertyUpdates(const QObject *const object, const QJsonObject &objectInfo)
      + {
      ++    auto *signalHandler = signalHandlerFor(object);
      +     foreach (const QJsonValue &propertyInfoVar, objectInfo[KEY_PROPERTIES].toArray()) {
      +         const QJsonArray &propertyInfo = propertyInfoVar.toArray();
      +         if (propertyInfo.size() < 2) {
      +@@ -353,19 +352,19 @@ void QMetaObjectPublisher::initializePropertyUpdates(const QObject *const object
      + 
      +         // Only connect for a property update once
      +         if (connectedProperties.isEmpty()) {
      +-            signalHandler.connectTo(object, signalIndex);
      ++            signalHandler->connectTo(object, signalIndex);
      +         }
      + 
      +         connectedProperties.insert(propertyIndex);
      +     }
      + 
      +     // also always connect to destroyed signal
      +-    signalHandler.connectTo(object, s_destroyedSignalIndex);
      ++    signalHandler->connectTo(object, s_destroyedSignalIndex);
      + }
      + 
      + void QMetaObjectPublisher::sendPendingPropertyUpdates()
      + {
      +-    if (blockUpdates || !clientIsIdle || pendingPropertyUpdates.isEmpty()) {
      ++    if (blockUpdates) {
      +         return;
      +     }
      + 
      +@@ -415,18 +414,19 @@ void QMetaObjectPublisher::sendPendingPropertyUpdates()
      + 
      +     // data does not contain specific updates
      +     if (!data.isEmpty()) {
      +-        setClientIsIdle(false);
      +-
      +         message[KEY_DATA] = data;
      +-        broadcastMessage(message);
      ++        enqueueBroadcastMessage(message);
      +     }
      + 
      +     // send every property update which is not supposed to be broadcasted
      +     const QHash::const_iterator suend = specificUpdates.constEnd();
      +     for (QHash::const_iterator it = specificUpdates.constBegin(); it != suend; ++it) {
      +         message[KEY_DATA] = it.value();
      +-        it.key()->sendMessage(message);
      ++        enqueueMessage(message, it.key());
      +     }
      ++
      ++    for (auto state = transportState.begin(); state != transportState.end(); ++state)
      ++        sendEnqueuedPropertyUpdates(state.key());
      + }
      + 
      + QVariant QMetaObjectPublisher::invokeMethod(QObject *const object, const QMetaMethod &method,
      +@@ -572,7 +572,7 @@ void QMetaObjectPublisher::signalEmitted(const QObject *object, const int signal
      +         }
      +     } else {
      +         pendingPropertyUpdates[object][signalIndex] = arguments;
      +-        if (clientIsIdle && !blockUpdates && !timer.isActive()) {
      ++        if (!blockUpdates && !timer.isActive()) {
      +             timer.start(PROPERTY_UPDATE_INTERVAL, this);
      +         }
      +     }
      +@@ -590,7 +590,7 @@ void QMetaObjectPublisher::objectDestroyed(const QObject *object)
      +     // only remove from handler when we initialized the property updates
      +     // cf: https://bugreports.qt.io/browse/QTBUG-60250
      +     if (propertyUpdatesInitialized) {
      +-        signalHandler.remove(object);
      ++        signalHandlerFor(object)->remove(object);
      +         signalToPropertyMap.remove(object);
      +     }
      +     pendingPropertyUpdates.remove(object);
      +@@ -852,6 +852,52 @@ void QMetaObjectPublisher::broadcastMessage(const QJsonObject &message) const
      +     }
      + }
      + 
      ++void QMetaObjectPublisher::enqueueBroadcastMessage(const QJsonObject &message)
      ++{
      ++    if (webChannel->d_func()->transports.isEmpty()) {
      ++        qWarning("QWebChannel is not connected to any transports, cannot send message: %s",
      ++                 QJsonDocument(message).toJson().constData());
      ++        return;
      ++    }
      ++
      ++    for (auto *transport : webChannel->d_func()->transports) {
      ++        auto &state = transportState[transport];
      ++        state.queuedMessages.append(message);
      ++    }
      ++}
      ++
      ++void QMetaObjectPublisher::enqueueMessage(const QJsonObject &message,
      ++                                          QWebChannelAbstractTransport *transport)
      ++{
      ++    auto &state = transportState[transport];
      ++    state.queuedMessages.append(message);
      ++}
      ++
      ++void QMetaObjectPublisher::sendEnqueuedPropertyUpdates(QWebChannelAbstractTransport *transport)
      ++{
      ++    auto found = transportState.find(transport);
      ++    if (found != transportState.end() && found.value().clientIsIdle
      ++        && !found.value().queuedMessages.isEmpty()) {
      ++
      ++        // If the client is connected with an in-process transport, it can
      ++        // happen that a message triggers a subsequent property change. In
      ++        // that case, we need to ensure that the queued messages have already
      ++        // been cleared; otherwise the recursive call will send everythig again.
      ++        // Case in point: The qmlwebchannel tests fail if we don't clear the
      ++        // queued messages before sending them out.
      ++        // For that same reason set the client to "busy" (aka non-idle) just
      ++        // right before sending out the messages; otherwise a potential
      ++        // "Idle" type message will not correctly restore the Idle state.
      ++        const auto messages = std::move(found.value().queuedMessages);
      ++        Q_ASSERT(found.value().queuedMessages.isEmpty());
      ++        found.value().clientIsIdle = false;
      ++
      ++        for (const auto &message : messages) {
      ++            transport->sendMessage(message);
      ++        }
      ++    }
      ++}
      ++
      + void QMetaObjectPublisher::handleMessage(const QJsonObject &message, QWebChannelAbstractTransport *transport)
      + {
      +     if (!webChannel->d_func()->transports.contains(transport)) {
      +@@ -866,7 +912,7 @@ void QMetaObjectPublisher::handleMessage(const QJsonObject &message, QWebChannel
      + 
      +     const MessageType type = toType(message.value(KEY_TYPE));
      +     if (type == TypeIdle) {
      +-        setClientIsIdle(true);
      ++        setClientIsIdle(true, transport);
      +     } else if (type == TypeInit) {
      +         if (!message.contains(KEY_ID)) {
      +             qWarning("JSON message object is missing the id property: %s",
      +@@ -913,9 +959,9 @@ void QMetaObjectPublisher::handleMessage(const QJsonObject &message, QWebChannel
      +                 return;
      +             transport->sendMessage(createResponse(message.value(KEY_ID), wrapResult(result, transport)));
      +         } else if (type == TypeConnectToSignal) {
      +-            signalHandler.connectTo(object, message.value(KEY_SIGNAL).toInt(-1));
      ++            signalHandlerFor(object)->connectTo(object, message.value(KEY_SIGNAL).toInt(-1));
      +         } else if (type == TypeDisconnectFromSignal) {
      +-            signalHandler.disconnectFrom(object, message.value(KEY_SIGNAL).toInt(-1));
      ++            signalHandlerFor(object)->disconnectFrom(object, message.value(KEY_SIGNAL).toInt(-1));
      +         } else if (type == TypeSetProperty) {
      +             setProperty(object, message.value(KEY_PROPERTY).toInt(-1),
      +                         message.value(KEY_VALUE));
      +@@ -931,6 +977,7 @@ void QMetaObjectPublisher::setBlockUpdates(bool block)
      +     blockUpdates = block;
      + 
      +     if (!blockUpdates) {
      ++        timer.start(PROPERTY_UPDATE_INTERVAL, this);
      +         sendPendingPropertyUpdates();
      +     } else if (timer.isActive()) {
      +         timer.stop();
      +@@ -948,4 +995,15 @@ void QMetaObjectPublisher::timerEvent(QTimerEvent *event)
      +     }
      + }
      + 
      ++SignalHandler *QMetaObjectPublisher::signalHandlerFor(const QObject *object)
      ++{
      ++    auto thread = object->thread();
      ++    auto it = signalHandlers.find(thread);
      ++    if (it == signalHandlers.end()) {
      ++        it = signalHandlers.emplace(thread, this).first;
      ++        it->second.moveToThread(thread);
      ++    }
      ++    return &it->second;
      ++}
      ++
      + QT_END_NAMESPACE
      +diff --git a/qtwebchannel/src/webchannel/qmetaobjectpublisher_p.h b/qtwebchannel/src/webchannel/qmetaobjectpublisher_p.h
      +index bbd9875..4713ef1 100644
      +--- a/qtwebchannel/src/webchannel/qmetaobjectpublisher_p.h
      ++++ b/qtwebchannel/src/webchannel/qmetaobjectpublisher_p.h
      +@@ -59,6 +59,9 @@
      + #include 
      + #include 
      + #include 
      ++#include 
      ++
      ++#include 
      + 
      + #include "qwebchannelglobal.h"
      + 
      +@@ -109,17 +112,36 @@ public:
      +      */
      +     void broadcastMessage(const QJsonObject &message) const;
      + 
      ++    /**
      ++     * Enqueue the given @p message to all known transports.
      ++     */
      ++    void enqueueBroadcastMessage(const QJsonObject &message);
      ++
      ++    /**
      ++     * Enqueue the given @p message to @p transport.
      ++     */
      ++    void enqueueMessage(const QJsonObject &message, QWebChannelAbstractTransport *transport);
      ++
      ++    /**
      ++     * If client for given @p transport is idle, send queued messaged to @p transport and then mark
      ++     * the client as not idle.
      ++     */
      ++    void sendEnqueuedPropertyUpdates(QWebChannelAbstractTransport *transport);
      ++
      +     /**
      +      * Serialize the QMetaObject of @p object and return it in JSON form.
      +      */
      +     QJsonObject classInfoForObject(const QObject *object, QWebChannelAbstractTransport *transport);
      + 
      +     /**
      +-     * Set the client to idle or busy, based on the value of @p isIdle.
      +-     *
      +-     * When the value changed, start/stop the property update timer accordingly.
      ++     * Set the client to idle or busy for a single @p transport, based on the value of @p isIdle.
      ++     */
      ++    void setClientIsIdle(bool isIdle, QWebChannelAbstractTransport *transport);
      ++
      ++    /**
      ++     * Check that client is idle for @p transport.
      +      */
      +-    void setClientIsIdle(bool isIdle);
      ++    bool isClientIdle(QWebChannelAbstractTransport *transport);
      + 
      +     /**
      +      * Initialize clients by sending them the class information of the registered objects.
      +@@ -272,10 +294,18 @@ private:
      +     friend class TestWebChannel;
      + 
      +     QWebChannel *webChannel;
      +-    SignalHandler signalHandler;
      ++    std::unordered_map> signalHandlers;
      ++    SignalHandler *signalHandlerFor(const QObject *object);
      + 
      +-    // true when the client is idle, false otherwise
      +-    bool clientIsIdle;
      ++    struct TransportState
      ++    {
      ++        TransportState() : clientIsIdle(false) { }
      ++        // true when the client is idle, false otherwise
      ++        bool clientIsIdle;
      ++        // messages to send
      ++        QQueue queuedMessages;
      ++    };
      ++    QHash transportState;
      + 
      +     // true when no property updates should be sent, false otherwise
      +     bool blockUpdates;
      +diff --git a/qtwebchannel/src/webchannel/signalhandler_p.h b/qtwebchannel/src/webchannel/signalhandler_p.h
      +index 27afadb..d77373c 100644
      +--- a/qtwebchannel/src/webchannel/signalhandler_p.h
      ++++ b/qtwebchannel/src/webchannel/signalhandler_p.h
      +@@ -56,6 +56,7 @@
      + #include 
      + #include 
      + #include 
      ++#include 
      + 
      + QT_BEGIN_NAMESPACE
      + 
      +@@ -71,6 +72,7 @@ static const int s_destroyedSignalIndex = QObject::staticMetaObject.indexOfMetho
      + template
      + class SignalHandler : public QObject
      + {
      ++    Q_DISABLE_COPY(SignalHandler)
      + public:
      +     SignalHandler(Receiver *receiver, QObject *parent = 0);
      + 
      +@@ -268,6 +270,7 @@ int SignalHandler::qt_metacall(QMetaObject::Call call, int methodId, v
      +     if (call == QMetaObject::InvokeMetaMethod) {
      +         const QObject *object = sender();
      +         Q_ASSERT(object);
      ++        Q_ASSERT(QThread::currentThread() == object->thread());
      +         Q_ASSERT(senderSignalIndex() == methodId);
      +         Q_ASSERT(m_connectionsCounter.contains(object));
      +         Q_ASSERT(m_connectionsCounter.value(object).contains(methodId));
      +diff --git a/qtwebchannel/tests/auto/qml/testwebchannel.cpp b/qtwebchannel/tests/auto/qml/testwebchannel.cpp
      +index 9891687..3ca81c2 100644
      +--- a/qtwebchannel/tests/auto/qml/testwebchannel.cpp
      ++++ b/qtwebchannel/tests/auto/qml/testwebchannel.cpp
      +@@ -46,7 +46,11 @@ TestWebChannel::~TestWebChannel()
      + 
      + bool TestWebChannel::clientIsIdle() const
      + {
      +-    return QWebChannel::d_func()->publisher->clientIsIdle;
      ++    for (auto *transport : QWebChannel::d_func()->transports) {
      ++        if (QWebChannel::d_func()->publisher->isClientIdle(transport))
      ++            return true;
      ++    }
      ++    return false;
      + }
      + 
      + QT_END_NAMESPACE
      +diff --git a/qtwebchannel/tests/auto/webchannel/tst_webchannel.cpp b/qtwebchannel/tests/auto/webchannel/tst_webchannel.cpp
      +index 181da9e..37f989a 100644
      +--- a/qtwebchannel/tests/auto/webchannel/tst_webchannel.cpp
      ++++ b/qtwebchannel/tests/auto/webchannel/tst_webchannel.cpp
      +@@ -785,7 +785,7 @@ void TestWebChannel::testTransportWrapObjectProperties()
      +     DummyTransport *dummyTransport = new DummyTransport(this);
      +     channel.connectTo(dummyTransport);
      +     channel.d_func()->publisher->initializeClient(dummyTransport);
      +-    channel.d_func()->publisher->setClientIsIdle(true);
      ++    channel.d_func()->publisher->setClientIsIdle(true, dummyTransport);
      + 
      +     QCOMPARE(channel.d_func()->publisher->transportedWrappedObjects.size(), 0);
      + 
      +@@ -943,8 +943,6 @@ void TestWebChannel::testInfiniteRecursion()
      + 
      + void TestWebChannel::testAsyncObject()
      + {
      +-    QSKIP("This test is broken. See QTBUG-80729");
      +-
      +     QWebChannel channel;
      +     channel.connectTo(m_dummyTransport);
      + 
      +@@ -990,6 +988,50 @@ void TestWebChannel::testAsyncObject()
      +     thread.wait();
      + }
      + 
      ++void TestWebChannel::testPropertyMultipleTransports()
      ++{
      ++    DummyTransport transport1;
      ++    DummyTransport transport2;
      ++
      ++    QWebChannel channel;
      ++    QMetaObjectPublisher *publisher = channel.d_func()->publisher;
      ++
      ++    TestObject testObj;
      ++    testObj.setObjectName("testObject");
      ++    channel.registerObject(testObj.objectName(), &testObj);
      ++    channel.connectTo(&transport1);
      ++    channel.connectTo(&transport2);
      ++
      ++    testObj.setProp("Hello");
      ++
      ++    publisher->initializeClient(&transport1);
      ++    publisher->initializeClient(&transport2);
      ++    publisher->setClientIsIdle(true, &transport1);
      ++    QCOMPARE(publisher->isClientIdle(&transport1), true);
      ++    QCOMPARE(publisher->isClientIdle(&transport2), false);
      ++    QVERIFY(transport1.messagesSent().isEmpty());
      ++    QVERIFY(transport2.messagesSent().isEmpty());
      ++
      ++    testObj.setProp("World");
      ++    QTRY_COMPARE_WITH_TIMEOUT(transport1.messagesSent().size(), 1u, 2000);
      ++    QCOMPARE(transport2.messagesSent().size(), 0u);
      ++    publisher->setClientIsIdle(true, &transport2);
      ++    QTRY_COMPARE_WITH_TIMEOUT(transport2.messagesSent().size(), 1u, 2000);
      ++    QCOMPARE(publisher->isClientIdle(&transport1), false);
      ++    QCOMPARE(publisher->isClientIdle(&transport2), false);
      ++
      ++    testObj.setProp("!!!");
      ++    publisher->setClientIsIdle(true, &transport2);
      ++    QCOMPARE(publisher->isClientIdle(&transport2), true);
      ++    QCOMPARE(publisher->isClientIdle(&transport1), false);
      ++    QTRY_COMPARE_WITH_TIMEOUT(transport2.messagesSent().size(), 2u, 2000);
      ++    QCOMPARE(transport1.messagesSent().size(), 1u);
      ++    publisher->setClientIsIdle(true, &transport1);
      ++    QTRY_COMPARE_WITH_TIMEOUT(transport1.messagesSent().size(), 2u, 2000);
      ++    QCOMPARE(publisher->isClientIdle(&transport1), false);
      ++    QCOMPARE(publisher->isClientIdle(&transport2), false);
      ++}
      ++
      + class FunctionWrapper : public QObject
      + {
      +     Q_OBJECT
      +@@ -1082,7 +1124,7 @@ void TestWebChannel::benchInitializeClients()
      + 
      +         publisher->propertyUpdatesInitialized = false;
      +         publisher->signalToPropertyMap.clear();
      +-        publisher->signalHandler.clear();
      ++        publisher->signalHandlers.clear();
      +     }
      + }
      + 
      +@@ -1107,7 +1149,7 @@ void TestWebChannel::benchPropertyUpdates()
      +             obj->change();
      +         }
      + 
      +-        channel.d_func()->publisher->clientIsIdle = true;
      ++        channel.d_func()->publisher->setClientIsIdle(true, m_dummyTransport);
      +         channel.d_func()->publisher->sendPendingPropertyUpdates();
      +     }
      + }
      +diff --git a/qtwebchannel/tests/auto/webchannel/tst_webchannel.h b/qtwebchannel/tests/auto/webchannel/tst_webchannel.h
      +index eae21f4..dd4e690 100644
      +--- a/qtwebchannel/tests/auto/webchannel/tst_webchannel.h
      ++++ b/qtwebchannel/tests/auto/webchannel/tst_webchannel.h
      +@@ -348,6 +348,7 @@ private slots:
      +     void testJsonToVariant();
      +     void testInfiniteRecursion();
      +     void testAsyncObject();
      ++    void testPropertyMultipleTransports();
      +     void testDeletionDuringMethodInvocation_data();
      +     void testDeletionDuringMethodInvocation();
      + 
      +Submodule qtwebengine f328054d...38e0df6c (commits not present)
      +Submodule qtwebsockets 65850954..63fb8da1:
      +diff --git a/qtwebsockets/src/websockets/qwebsocketdataprocessor.cpp b/qtwebsockets/src/websockets/qwebsocketdataprocessor.cpp
      +index 2affdd5..95f1194 100644
      +--- a/qtwebsockets/src/websockets/qwebsocketdataprocessor.cpp
      ++++ b/qtwebsockets/src/websockets/qwebsocketdataprocessor.cpp
      +@@ -273,6 +273,7 @@ void QWebSocketDataProcessor::clear()
      +     if (!m_pConverterState)
      +         m_pConverterState = new QTextCodec::ConverterState(QTextCodec::ConvertInvalidToNull |
      +                                                            QTextCodec::IgnoreHeader);
      ++    frame.clear();
      + }
      + 
      + /*!
      +diff --git a/qtwebsockets/src/websockets/qwebsocketprotocol.cpp b/qtwebsockets/src/websockets/qwebsocketprotocol.cpp
      +index df87a93..d0465f1 100644
      +--- a/qtwebsockets/src/websockets/qwebsocketprotocol.cpp
      ++++ b/qtwebsockets/src/websockets/qwebsocketprotocol.cpp
      +@@ -210,7 +210,7 @@ void QWebSocketProtocol::mask(char *payload, quint64 size, quint32 maskingKey)
      +                             quint8((maskingKey & 0x0000FF00u) >> 8),
      +                             quint8((maskingKey & 0x000000FFu))
      +                           };
      +-    int i = 0;
      ++    quint64 i = 0;
      +     while (size-- > 0)
      +         *payload++ ^= mask[i++ % 4];
      + }
      diff --git a/srcpkgs/qt5/template b/srcpkgs/qt5/template
      index a79d25e69da8..6dddce7f3e46 100644
      --- a/srcpkgs/qt5/template
      +++ b/srcpkgs/qt5/template
      @@ -2,11 +2,11 @@
       #
       # revbump libqtxdg after bumping patch version
       pkgname=qt5
      -version=5.15.7+20221119
      +version=5.15.8
      +revision=1
      +build_style=meta
       # commit f8c9fb304bc3e53b3aa07f962cd74e9160decccc
       # base repo: https://invent.kde.org/qt/qt/qt5
      -revision=5
      -build_style=meta
       hostmakedepends="cmake clang flex perl glib-devel pkg-config
        python re2c ruby which"
       makedepends="SDL2-devel Vulkan-Headers alsa-lib-devel double-conversion-devel
      @@ -29,8 +29,9 @@ homepage="https://qt.io/"
       # tarball is generated with `git archive-all qt5-$version.tar.gz`
       # to keep the size smaller qtwebengine, qtwebview, qtdocgallery, qtactiveqt and qtpim
       # can be marked with the export-ignore attribute
      -distfiles="https://void.johnnynator.dev/distfiles/qt5-${version}.tar.gz"
      -checksum=9d57af471c78029a362276b7c99108ea009f511bb9ba6ff6cb884f6ddd255e9f
      +#distfiles="https://void.johnnynator.dev/distfiles/qt5-${version}.tar.gz"
      +distfiles="https://download.qt.io/archive/qt/5.15/${version}/single/qt-everywhere-opensource-src-${version}.tar.xz"
      +checksum=776a9302c336671f9406a53bd30b8e36f825742b2ec44a57c08217bff0fa86b9
       python_version=2 #unverified
       replaces="qt5-doc<5.6.0 qt5-quick1<5.6.0 qt5-quick1-devel<5.6.0 qt5-webkit<5.6.0 qt5-webkit-devel<5.6.0
        qt5-enginio<5.7.1 qt5-enginio-devel<5.7.1 qt5-plugin-gtk<5.7.1 qt5-canvas3d<5.13.0"
      @@ -250,7 +251,6 @@ do_configure() {
       	# opts+=" -v"
       	opts+=" -skip qtwebengine"
       	opts+=" -skip qtwebview"
      -	opts+=" -skip qtdocgallery"
       	opts+=" -skip qtpim"
       	opts+=" -skip qtsystems"
       	opts+=" -skip qtspeech"
      
      From 07f9e418df0e95689228438b5cd8f772c8d5c498 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Wed, 22 Mar 2023 20:01:51 -0400
      Subject: [PATCH 073/113] qtav: revbump for ffmpeg4-4.4.3
      
      ---
       srcpkgs/qtav/template | 4 ++--
       1 file changed, 2 insertions(+), 2 deletions(-)
      
      diff --git a/srcpkgs/qtav/template b/srcpkgs/qtav/template
      index 34c30b2c0c78..2d00ad104355 100644
      --- a/srcpkgs/qtav/template
      +++ b/srcpkgs/qtav/template
      @@ -1,10 +1,10 @@
       # Template file for 'qtav'
       pkgname=qtav
       version=1.13.0
      -revision=1
      +revision=2
       build_style=qmake
       hostmakedepends="qt5-qmake qt5-host-tools"
      -makedepends="ffmpeg-devel libass-devel libopenal-devel
      +makedepends="ffmpeg4-devel libass-devel libopenal-devel
        libva-glx-devel libXv-devel pulseaudio-devel
        qt5-declarative-devel qt5-svg-devel
        qt5-quickcontrols"
      
      From 8b7025fdeeb68bf8ce545fe3cbd96c4c0fcb2ab0 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Wed, 22 Mar 2023 20:01:51 -0400
      Subject: [PATCH 074/113] qtox: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/qtox/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/qtox/template b/srcpkgs/qtox/template
      index 16019d7eaec9..5cea0b11b697 100644
      --- a/srcpkgs/qtox/template
      +++ b/srcpkgs/qtox/template
      @@ -1,7 +1,7 @@
       # Template file for 'qtox'
       pkgname=qtox
       version=1.17.6
      -revision=2
      +revision=3
       build_style=cmake
       configure_args="-DUPDATE_CHECK=OFF
        -DGIT_DESCRIBE=${version}
      
      From 333666008f8d0c907795ac5a126cbc4d22ada441 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Wed, 22 Mar 2023 20:01:51 -0400
      Subject: [PATCH 075/113] retroarch: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/retroarch/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/retroarch/template b/srcpkgs/retroarch/template
      index 28016aa0129e..20a1415913be 100644
      --- a/srcpkgs/retroarch/template
      +++ b/srcpkgs/retroarch/template
      @@ -1,7 +1,7 @@
       # Template file for 'retroarch'
       pkgname=retroarch
       version=1.15.0
      -revision=1
      +revision=2
       build_style=configure
       configure_args="--prefix=/usr --sysconfdir=/etc --enable-networking
        --enable-udev --disable-builtinflac --disable-builtinglslang
      
      From 960e55dadbbdbdb8f8993e88f1c7bb0f1a5ed30d Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Wed, 22 Mar 2023 20:01:51 -0400
      Subject: [PATCH 076/113] scrcpy: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/scrcpy/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/scrcpy/template b/srcpkgs/scrcpy/template
      index 06208c389ca9..a5de935c7def 100644
      --- a/srcpkgs/scrcpy/template
      +++ b/srcpkgs/scrcpy/template
      @@ -1,7 +1,7 @@
       # Template file for 'scrcpy'
       pkgname=scrcpy
       version=2.1
      -revision=1
      +revision=2
       build_style=meson
       configure_args="-Dcompile_server=false
        -Dprebuilt_server=/usr/share/scrcpy/scrcpy-server-v${version}"
      
      From f5906f05caf1b039a36e4452776bbb51ebe7efbd Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Wed, 22 Mar 2023 20:01:51 -0400
      Subject: [PATCH 077/113] spek-alternative: revbump for ffmpeg4-4.4.3
      
      ---
       srcpkgs/spek-alternative/template | 6 +++---
       1 file changed, 3 insertions(+), 3 deletions(-)
      
      diff --git a/srcpkgs/spek-alternative/template b/srcpkgs/spek-alternative/template
      index d65086b8f008..05246f1b8d0c 100644
      --- a/srcpkgs/spek-alternative/template
      +++ b/srcpkgs/spek-alternative/template
      @@ -1,11 +1,11 @@
       # Template file for 'spek-alternative'
       pkgname=spek-alternative
       version=0.8.2.3
      -revision=1
      +revision=2
       build_style=gnu-configure
       hostmakedepends="automake gettext-devel intltool libtool pkg-config wxWidgets-common"
      -makedepends="ffmpeg-devel wxWidgets-gtk3-devel"
      -depends="ffmpeg"
      +makedepends="ffmpeg4-devel wxWidgets-gtk3-devel"
      +depends="ffmpeg4"
       short_desc="Acoustic spectrum analyser"
       maintainer="Kartik Singh "
       license="GPL-3.0-or-later"
      
      From 3f4d164b94becf46041dee99e9bd9fb07212b525 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Wed, 22 Mar 2023 20:01:51 -0400
      Subject: [PATCH 078/113] ssr: revbump for ffmpeg4-4.4.3
      
      ---
       srcpkgs/ssr/template | 4 ++--
       1 file changed, 2 insertions(+), 2 deletions(-)
      
      diff --git a/srcpkgs/ssr/template b/srcpkgs/ssr/template
      index b055b9ec0774..3448ca110eb0 100644
      --- a/srcpkgs/ssr/template
      +++ b/srcpkgs/ssr/template
      @@ -1,11 +1,11 @@
       # Template file for 'ssr'
       pkgname=ssr
       version=0.4.4
      -revision=1
      +revision=2
       build_style=cmake
       configure_args="-DWITH_QT5=ON"
       hostmakedepends="pkg-config"
      -makedepends="alsa-lib-devel ffmpeg-devel glu-devel jack-devel pulseaudio-devel
      +makedepends="alsa-lib-devel ffmpeg4-devel glu-devel jack-devel pulseaudio-devel
        qt5-tools-devel qt5-x11extras-devel libXinerama-devel v4l-utils-devel"
       depends="desktop-file-utils hicolor-icon-theme"
       short_desc="Simple Screen Recorder for programs and games"
      
      From 7e927ff3fe535dadc79ecd1ba9810586b9d268e4 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Wed, 22 Mar 2023 20:01:51 -0400
      Subject: [PATCH 079/113] sumo: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/sumo/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/sumo/template b/srcpkgs/sumo/template
      index 0f9b9ec815f5..a3fe134aa5ac 100644
      --- a/srcpkgs/sumo/template
      +++ b/srcpkgs/sumo/template
      @@ -1,7 +1,7 @@
       # Template file for 'sumo'
       pkgname=sumo
       version=1.12.0
      -revision=5
      +revision=6
       build_style=cmake
       hostmakedepends="libgdal-tools pkg-config swig python3-setuptools"
       makedepends="python3-devel ffmpeg-devel fox-devel gl2ps-devel libgdal-devel
      
      From 8822756174a2753faee503aa7831a480783d559a Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Wed, 22 Mar 2023 20:01:52 -0400
      Subject: [PATCH 080/113] synfig: revbump for ffmpeg-6.0 and mlt7
      
      ---
       srcpkgs/synfig/patches/ffmpeg6.patch | 71 ++++++++++++++++++++++++++++
       srcpkgs/synfig/template              |  6 +--
       2 files changed, 74 insertions(+), 3 deletions(-)
       create mode 100644 srcpkgs/synfig/patches/ffmpeg6.patch
      
      diff --git a/srcpkgs/synfig/patches/ffmpeg6.patch b/srcpkgs/synfig/patches/ffmpeg6.patch
      new file mode 100644
      index 000000000000..10780b42782f
      --- /dev/null
      +++ b/srcpkgs/synfig/patches/ffmpeg6.patch
      @@ -0,0 +1,71 @@
      +--- a/src/modules/mod_libavcodec/trgt_av.cpp	2022-10-25 09:14:12.000000000 -0400
      ++++ b/src/modules/mod_libavcodec/trgt_av.cpp	2023-05-05 21:34:17.899194559 -0400
      +@@ -38,6 +41,7 @@
      + extern "C"
      + {
      + #ifdef HAVE_LIBAVFORMAT_AVFORMAT_H
      ++#	include 
      + #	include 
      + #elif defined(HAVE_AVFORMAT_H)
      + #	include 
      +@@ -155,11 +156,11 @@
      +     }
      + 
      + 	bool open_video_stream() {
      +-		if (avcodec_open2(video_context, NULL, NULL) < 0) {
      ++		if (avcodec_open2(video_context, nullptr, nullptr) < 0) {
      + 			synfig::error("Target_LibAVCodec: could not open video codec");
      + 			// seems the calling of avcodec_free_context after error will cause crash
      + 			// so just forget about this context
      +-			video_context = NULL;
      ++			video_context = nullptr;
      + 			close();
      + 			return false;
      +         }
      +@@ -234,15 +235,21 @@
      + 		close();
      + 
      + 		if (!av_registered) {
      ++#if LIBAVCODEC_VERSION_MAJOR < 58 // FFMPEG < 4.0
      + 			av_register_all();
      ++#endif
      + 			av_registered = true;
      + 		}
      + 
      + 		// guess format
      +-		AVOutputFormat *format = av_guess_format(NULL, filename.c_str(), NULL);
      ++#if LIBAVCODEC_VERSION_MAJOR < 59 // FFMPEG < 5.0
      ++		AVOutputFormat* format = av_guess_format(nullptr, filename.c_str(), nullptr);
      ++#else
      ++		const AVOutputFormat* format = av_guess_format(nullptr, filename.c_str(), nullptr);
      ++#endif
      + 		if (!format) {
      + 			synfig::warning("Target_LibAVCodec: unable to guess the output format, defaulting to MPEG");
      +-			format = av_guess_format("mpeg", NULL, NULL);
      ++			format = av_guess_format("mpeg", nullptr, nullptr);
      + 		}
      + 		if (!format) {
      + 			synfig::error("Target_LibAVCodec: unable to find 'mpeg' output format");
      +@@ -254,6 +261,7 @@
      + 		context = avformat_alloc_context();
      + 		assert(context);
      + 		context->oformat = format;
      ++#if LIBAVCODEC_VERSION_MAJOR < 58 // FFMPEG < 4.0
      + 		if (filename.size() + 1 > sizeof(context->filename)) {
      + 			synfig::error(
      + 				"Target_LibAVCodec: filename too long, max length is %d, filename is '%s'",
      +@@ -263,6 +271,14 @@
      + 			return false;
      + 		}
      + 		memcpy(context->filename, filename.c_str(), filename.size() + 1);
      ++#else
      ++		context->url = av_strndup(filename.c_str(), filename.size());
      ++		if (!context->url) {
      ++			synfig::error("Target_LibAVCodec: cannot allocate space for filename");
      ++			close();
      ++			return false;
      ++		}
      ++#endif
      + 
      + 		packet = av_packet_alloc();
      + 		assert(packet);
      diff --git a/srcpkgs/synfig/template b/srcpkgs/synfig/template
      index 30109541ec4f..703cfd7ebac8 100644
      --- a/srcpkgs/synfig/template
      +++ b/srcpkgs/synfig/template
      @@ -2,11 +2,11 @@
       # Should be kept in sync with 'synfigstudio' and 'ETL'
       pkgname=synfig
       version=1.4.4
      -revision=3
      +revision=4
       build_style=gnu-configure
       configure_args="--with-boost-libdir=${XBPS_CROSS_BASE}/usr/lib"
       hostmakedepends="boost-build ImageMagick pkg-config intltool"
      -makedepends="ETL gettext-devel libxml++-devel mlt-devel libmagick-devel
      +makedepends="ETL gettext-devel libxml++-devel mlt7-devel libmagick-devel
        libmng-devel boost-build boost-devel libopenexr-devel ffmpeg-devel"
       depends="ImageMagick"
       short_desc="CLI 2D vector and timeline-based animation software"
      @@ -20,7 +20,7 @@ CXXFLAGS="-std=c++11 -DHAVE_LOCALE_H=1"
       
       synfig-devel_package() {
       	depends="${sourcepkg}>=${version}_${revision}
      -	 libopenexr-devel libxml++-devel mlt-devel"
      +	 libopenexr-devel libxml++-devel mlt7-devel"
       	short_desc+=" - development files"
       	pkg_install() {
       		vmove usr/bin/synfig-config
      
      From fa6964dd7790c038a16826e838e30810dfd0887f Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Wed, 22 Mar 2023 20:01:52 -0400
      Subject: [PATCH 081/113] tg_owt: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/tg_owt/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/tg_owt/template b/srcpkgs/tg_owt/template
      index 97d195ddb34a..551614b24956 100644
      --- a/srcpkgs/tg_owt/template
      +++ b/srcpkgs/tg_owt/template
      @@ -1,7 +1,7 @@
       # Template file for 'tg_owt'
       pkgname=tg_owt
       version=0.0.0.20230107
      -revision=1
      +revision=2
       _commit=5098730b9eb6173f0b52068fe2555b7c1015123a
       _libyuv_commit=00950840d1c9bcbb3eb6ebc5aac5793e71166c8b
       _abseil_commit=8c0b94e793a66495e0b1f34a5eb26bd7dc672db0
      
      From 5c3c404b622934625a12c3142215df710b8a5875 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Wed, 22 Mar 2023 20:01:52 -0400
      Subject: [PATCH 082/113] timg: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/timg/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/timg/template b/srcpkgs/timg/template
      index 2a2ab763d2fd..8fb4327535ef 100644
      --- a/srcpkgs/timg/template
      +++ b/srcpkgs/timg/template
      @@ -1,7 +1,7 @@
       # Template file for 'timg'
       pkgname=timg
       version=1.4.5
      -revision=1
      +revision=2
       build_style=cmake
       configure_args="-DWITH_OPENSLIDE_SUPPORT=off -Wno-dev"
       hostmakedepends="pkg-config git"
      
      From 37f63173ff5bb0b5fa47231a44916a0d4983eb8d Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Wed, 22 Mar 2023 20:01:52 -0400
      Subject: [PATCH 083/113] tvheadend: revbump for ffmpeg4-4.4.3
      
      ---
       srcpkgs/tvheadend/template | 4 ++--
       1 file changed, 2 insertions(+), 2 deletions(-)
      
      diff --git a/srcpkgs/tvheadend/template b/srcpkgs/tvheadend/template
      index e6b16d7ccf3b..46b52b6fb7f9 100644
      --- a/srcpkgs/tvheadend/template
      +++ b/srcpkgs/tvheadend/template
      @@ -1,14 +1,14 @@
       # Template file for 'tvheadend'
       pkgname=tvheadend
       version=4.2.8
      -revision=6
      +revision=7
       build_style=gnu-configure
       configure_args="--enable-dvbscan --disable-ffmpeg_static
       --disable-hdhomerun_static --disable-bintray_cache --disable-libx264_static
       --disable-libx265_static --disable-libvpx_static --disable-libtheora_static
       --disable-libvorbis_static --disable-libfdkaac_static"
       hostmakedepends="gettext pkg-config python git which"
      -makedepends="avahi-libs-devel openssl-devel zlib-devel libcurl-devel ffmpeg-devel"
      +makedepends="avahi-libs-devel openssl-devel zlib-devel libcurl-devel ffmpeg4-devel"
       short_desc="TV streaming server"
       maintainer="lemmi "
       license="GPL-3.0-only"
      
      From e9ce70891df44c9e6344d38e11857eeb6dbbcf51 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Wed, 22 Mar 2023 20:01:52 -0400
      Subject: [PATCH 084/113] unpaper: update to 7.0.0.
      
      ---
       srcpkgs/unpaper/template | 16 ++++++++--------
       1 file changed, 8 insertions(+), 8 deletions(-)
      
      diff --git a/srcpkgs/unpaper/template b/srcpkgs/unpaper/template
      index 38ed47a58401..1ff910e722af 100644
      --- a/srcpkgs/unpaper/template
      +++ b/srcpkgs/unpaper/template
      @@ -1,13 +1,13 @@
       # Template file for 'unpaper'
       pkgname=unpaper
      -version=6.1
      -revision=3
      -build_style=gnu-configure
      +version=7.0.0
      +revision=1
      +build_style=meson
      +hostmakedepends="pkg-config meson libxslt"
      +makedepends="ffmpeg-devel python3-Sphinx"
      +short_desc="Post-processing tool for scanned sheets of paper"
       maintainer="Orphaned "
      -hostmakedepends="pkg-config libxslt"
      -makedepends="ffmpeg-devel"
      -license="GPL-2"
      +license="GPL-2.0-or-later"
       homepage="https://www.flameeyes.eu/projects/unpaper"
      -short_desc="A post-processing tool for scanned sheets of paper"
       distfiles="https://www.flameeyes.eu/files/${pkgname}-${version}.tar.xz"
      -checksum=237c84f5da544b3f7709827f9f12c37c346cdf029b1128fb4633f9bafa5cb930
      +checksum=2575fbbf26c22719d1cb882b59602c9900c7f747118ac130883f63419be46a80
      
      From ed12bda552159cd702103463017d07f6f22c5e9b Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Wed, 22 Mar 2023 20:01:52 -0400
      Subject: [PATCH 085/113] vba-m: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/vba-m/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/vba-m/template b/srcpkgs/vba-m/template
      index ba153e0b58ca..aa6093645e97 100644
      --- a/srcpkgs/vba-m/template
      +++ b/srcpkgs/vba-m/template
      @@ -2,7 +2,7 @@
       pkgname=vba-m
       reverts=1292_2
       version=2.1.5
      -revision=1
      +revision=2
       build_style=cmake
       configure_args="-DENABLE_GTK=TRUE -DENABLE_FFMPEG=TRUE -DENABLE_LINK=TRUE -DCMAKE_BUILD_TYPE=Release"
       hostmakedepends="gettext pkg-config unzip zip yasm wxWidgets-gtk3-devel"
      
      From 4b6892c2659a0b06b1f13c39d6041628e35a7ac5 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Wed, 22 Mar 2023 20:01:52 -0400
      Subject: [PATCH 086/113] vice: revbump for ffmpeg4-4.4.3
      
      ---
       srcpkgs/vice/template | 4 ++--
       1 file changed, 2 insertions(+), 2 deletions(-)
      
      diff --git a/srcpkgs/vice/template b/srcpkgs/vice/template
      index fe9d33a81194..4beab2c5f9eb 100644
      --- a/srcpkgs/vice/template
      +++ b/srcpkgs/vice/template
      @@ -1,7 +1,7 @@
       # Template file for 'vice'
       pkgname=vice
       version=3.7.1
      -revision=1
      +revision=2
       build_style=gnu-configure
       configure_args="
       	$(vopt_enable sdl2 sdlui2)
      @@ -26,7 +26,7 @@ makedepends="
       	$(vopt_if gtk3 gtk+3-devel)
       	$(vopt_if gtk3 pulseaudio-devel)
       	$(vopt_if gtk3 pango-devel)
      -	$(vopt_if ffmpeg ffmpeg-devel)"
      +	$(vopt_if ffmpeg ffmpeg4-devel)"
       short_desc="Emulator for C64, C128, CBM-II, PET, VIC20, Plus4 and C16"
       maintainer="Orphaned "
       license="GPL-2.0-or-later"
      
      From 0c8e0fb5875a53dca2306c0e5976add145438e61 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Wed, 22 Mar 2023 20:01:52 -0400
      Subject: [PATCH 087/113] waypipe: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/waypipe/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/waypipe/template b/srcpkgs/waypipe/template
      index 5c4161900060..1a46fe27f7d8 100644
      --- a/srcpkgs/waypipe/template
      +++ b/srcpkgs/waypipe/template
      @@ -1,7 +1,7 @@
       # Template file for 'waypipe'
       pkgname=waypipe
       version=0.8.4
      -revision=1
      +revision=2
       build_style=meson
       # lto is off because it causes linking errors in armv6l and armv7l (due to NEON)
       configure_args="-Dwerror=false -Dwith_dmabuf=enabled -Dwith_lz4=enabled
      
      From 38e67558347d8ba8b7bfff93792c692fb257cb76 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Wed, 22 Mar 2023 20:01:52 -0400
      Subject: [PATCH 088/113] wf-recorder: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/wf-recorder/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/wf-recorder/template b/srcpkgs/wf-recorder/template
      index e278eb001600..5d014a5f28af 100644
      --- a/srcpkgs/wf-recorder/template
      +++ b/srcpkgs/wf-recorder/template
      @@ -1,7 +1,7 @@
       # Template file for 'wf-recorder'
       pkgname=wf-recorder
       version=0.3.0
      -revision=1
      +revision=2
       build_style=meson
       hostmakedepends="pkg-config scdoc wayland-devel"
       makedepends="wayland-protocols wayland-devel ffmpeg-devel x264-devel
      
      From a94bd83fa833fa99b7179eb526713edda87b0b09 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Wed, 22 Mar 2023 20:01:52 -0400
      Subject: [PATCH 089/113] xpra: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/xpra/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/xpra/template b/srcpkgs/xpra/template
      index 0a63fdb6c743..d5acc1981c5f 100644
      --- a/srcpkgs/xpra/template
      +++ b/srcpkgs/xpra/template
      @@ -1,7 +1,7 @@
       # Template file for 'xpra'
       pkgname=xpra
       version=4.4.6
      -revision=1
      +revision=2
       build_style=python3-module
       make_build_args="--without-cuda_kernels --without-cuda_rebuild"
       make_install_args="$(vopt_with docs) ${make_build_args}"
      
      From ab55a4f5916befadd758601f12e6ecf6b364a5a3 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Fri, 31 Mar 2023 09:07:40 -0400
      Subject: [PATCH 090/113] nv-codec-headers: update to 12.0.16.0
      
      ---
       srcpkgs/nv-codec-headers/template | 4 ++--
       1 file changed, 2 insertions(+), 2 deletions(-)
      
      diff --git a/srcpkgs/nv-codec-headers/template b/srcpkgs/nv-codec-headers/template
      index 3d422a61e489..251e057f826f 100644
      --- a/srcpkgs/nv-codec-headers/template
      +++ b/srcpkgs/nv-codec-headers/template
      @@ -1,6 +1,6 @@
       # Template file for 'nv-codec-headers'
       pkgname=nv-codec-headers
      -version=11.1.5.1
      +version=12.0.16.0
       revision=1
       build_style=gnu-makefile
       short_desc="FFmpeg version of headers required to interface with Nvidias codec APIs"
      @@ -8,7 +8,7 @@ maintainer="Orphaned "
       license="MIT"
       homepage="http://git.videolan.org/?p=ffmpeg/nv-codec-headers.git"
       distfiles="https://github.com/FFmpeg/nv-codec-headers/archive/n${version}.tar.gz"
      -checksum=d095fbd56aa93772471a323be0ebe65504a0f43f06c76a30b6d25da77b06ae9c
      +checksum=2a1533b65f55f9da52956faf0627ed3b74868ac0c7f269990edd21369113b48f
       
       post_install() {
       	sed -n '4,25p' include/ffnvcodec/nvEncodeAPI.h > LICENSE
      
      From a9fb66fa48ee4186e924726c5ac23068923cbd46 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Fri, 31 Mar 2023 09:08:40 -0400
      Subject: [PATCH 091/113] openimagedenoise: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/openimagedenoise/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/openimagedenoise/template b/srcpkgs/openimagedenoise/template
      index db5ccdb055cc..cb90045afb63 100644
      --- a/srcpkgs/openimagedenoise/template
      +++ b/srcpkgs/openimagedenoise/template
      @@ -1,7 +1,7 @@
       # Template file for 'openimagedenoise'
       pkgname=openimagedenoise
       version=1.4.3
      -revision=1
      +revision=2
       archs="x86_64*"
       build_style=cmake
       hostmakedepends="ispc python3"
      
      From 70397fe860b5a49531a195548fd16bf4ae0e2ec7 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Mon, 3 Apr 2023 23:31:45 -0400
      Subject: [PATCH 092/113] shotcut: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/shotcut/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/shotcut/template b/srcpkgs/shotcut/template
      index 7d2af7b0470b..c416c906ff73 100644
      --- a/srcpkgs/shotcut/template
      +++ b/srcpkgs/shotcut/template
      @@ -1,7 +1,7 @@
       # Template file for 'shotcut'
       pkgname=shotcut
       version=23.05.14
      -revision=1
      +revision=2
       build_style=cmake
       configure_args="-DSHOTCUT_VERSION=${version}"
       hostmakedepends="pkg-config qt6-tools-devel"
      
      From 8b0f54619bf135b53610d93559d8d9a8e70f2a69 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Mon, 3 Apr 2023 23:33:30 -0400
      Subject: [PATCH 093/113] shiboken2: revbump for qt5-5.15.8
      
      ---
       srcpkgs/shiboken2/patches/importlib-machinery-bypass.patch | 1 +
       srcpkgs/shiboken2/template                                 | 2 +-
       2 files changed, 2 insertions(+), 1 deletion(-)
       create mode 120000 srcpkgs/shiboken2/patches/importlib-machinery-bypass.patch
      
      diff --git a/srcpkgs/shiboken2/patches/importlib-machinery-bypass.patch b/srcpkgs/shiboken2/patches/importlib-machinery-bypass.patch
      new file mode 120000
      index 000000000000..efcf3249bd88
      --- /dev/null
      +++ b/srcpkgs/shiboken2/patches/importlib-machinery-bypass.patch
      @@ -0,0 +1 @@
      +../../python3-pyside2/patches/importlib-machinery-bypass.patch
      \ No newline at end of file
      diff --git a/srcpkgs/shiboken2/template b/srcpkgs/shiboken2/template
      index 084ecc3ba1e1..2a21998997eb 100644
      --- a/srcpkgs/shiboken2/template
      +++ b/srcpkgs/shiboken2/template
      @@ -1,7 +1,7 @@
       # Template file for 'shiboken2'
       pkgname=shiboken2
       version=5.15.7
      -revision=1
      +revision=2
       _pkgname="pyside-setup-opensource-src-${version}"
       build_wrksrc="sources/shiboken2"
       build_style=cmake
      
      From d3469c611566e6c27c9e957b6fb662df133a23fc Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Mon, 3 Apr 2023 23:33:53 -0400
      Subject: [PATCH 094/113] python3-pyside2: update to 5.15.8
      
      ---
       .../patches/importlib-machinery-bypass.patch      | 15 +++++++++++++++
       srcpkgs/python3-pyside2/template                  |  9 +++++----
       2 files changed, 20 insertions(+), 4 deletions(-)
       create mode 100644 srcpkgs/python3-pyside2/patches/importlib-machinery-bypass.patch
      
      diff --git a/srcpkgs/python3-pyside2/patches/importlib-machinery-bypass.patch b/srcpkgs/python3-pyside2/patches/importlib-machinery-bypass.patch
      new file mode 100644
      index 000000000000..64c429584776
      --- /dev/null
      +++ b/srcpkgs/python3-pyside2/patches/importlib-machinery-bypass.patch
      @@ -0,0 +1,15 @@
      +Using this prevents an error around line 220 below it.
      +"AttributeError: module 'importlib' has no attribute 'machinery'"
      +The old backup logic is in place and compiles without issues.
      +--- a/sources/shiboken2/libshiboken/embed/signature_bootstrap.py	2023-04-02 23:09:34.688912402 -0400
      ++++ b/sources/shiboken2/libshiboken/embed/signature_bootstrap.py	2023-04-02 23:10:03.395529582 -0400
      +@@ -170,9 +170,6 @@
      +
      +     # 'zipstring_sequence' comes from signature.cpp
      +     zipbytes = base64.b64decode(''.join(zipstring_sequence))
      +-    if sys.version_info[0] >= 3:
      +-        vzip = zipfile.ZipFile(io.BytesIO(zipbytes))
      +-        return sys.meta_path, EmbeddableZipImporter(vzip)
      +
      +     # Old version for Python 2.7, only.
      +     import os
      diff --git a/srcpkgs/python3-pyside2/template b/srcpkgs/python3-pyside2/template
      index 50e6ff260d3b..b50e62bd215d 100644
      --- a/srcpkgs/python3-pyside2/template
      +++ b/srcpkgs/python3-pyside2/template
      @@ -1,11 +1,12 @@
       # Template file for 'python3-pyside2'
       pkgname=python3-pyside2
      -version=5.15.5
      -revision=2
      +version=5.15.8
      +revision=1
       _pkgname="pyside-setup-opensource-src-${version}"
       build_wrksrc="sources/pyside2"
       build_style=cmake
      -configure_args="-DPYTHON_EXECUTABLE=/usr/bin/python"
      +configure_args="-DPYTHON_EXECUTABLE=/usr/bin/python -DCMAKE_BUILD_TYPE=None
      + -DBUILD_TESTS=OFF"
       hostmakedepends="cmake python3 shiboken2"
       makedepends="python3-devel libshiboken2-devel qt5-devel
        qt5-multimedia-devel qt5-tools-devel qt5-plugin-mysql qt5-plugin-odbc
      @@ -23,7 +24,7 @@ maintainer="yopito "
       license="LGPL-3.0-or-later"
       homepage="https://wiki.qt.io/Qt_for_Python"
       distfiles="https://download.qt.io/official_releases/QtForPython/pyside2/PySide2-${version}-src/${_pkgname}.tar.xz"
      -checksum=3920a4fb353300260c9bc46ff70f1fb975c5e7efa22e9d51222588928ce19b33
      +checksum=23436302c8deb5b4cbc769b205d09604e38ba83b40708efccb7bd8c9af6f6b5d
       
       build_options="webengine"
       desc_option_webengine="Build Qt5 WebEngine bindings"
      
      From 1283bdb74e2bac200cb064b8498e6c42b12a68ce Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Tue, 4 Apr 2023 11:14:35 -0400
      Subject: [PATCH 095/113] konqueror: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/konqueror/template | 4 ++--
       1 file changed, 2 insertions(+), 2 deletions(-)
      
      diff --git a/srcpkgs/konqueror/template b/srcpkgs/konqueror/template
      index d8d0e73a78ab..c5bdba601d3c 100644
      --- a/srcpkgs/konqueror/template
      +++ b/srcpkgs/konqueror/template
      @@ -1,11 +1,11 @@
       # Template file for 'konqueror'
       pkgname=konqueror
       version=23.04.0
      -revision=1
      +revision=2
       build_style=cmake
       configure_args="-DDESKTOPTOJSON_EXECUTABLE=/usr/bin/desktoptojson"
       hostmakedepends="extra-cmake-modules python3 qt5-host-tools qt5-qmake kdoctools
      -kcoreaddons kconfig gettext"
      + kcoreaddons kconfig gettext"
       makedepends="qt5-devel qt5-webengine-devel qt5-declarative-devel
        qt5-webchannel-devel qt5-location-devel kcmutils-devel kdelibs4support-devel
        karchive-devel khtml-devel kdesu-devel kactivities5-devel"
      
      From c9d16345621ba50cbe8308a3e33e4b6c7db6b4da Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Tue, 4 Apr 2023 11:14:58 -0400
      Subject: [PATCH 096/113] qt5-speech: revbump for qt5-5.15.8
      
      ---
       srcpkgs/qt5-speech/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/qt5-speech/template b/srcpkgs/qt5-speech/template
      index 3ecd10d50650..2d7d4d4d2453 100644
      --- a/srcpkgs/qt5-speech/template
      +++ b/srcpkgs/qt5-speech/template
      @@ -1,7 +1,7 @@
       # Template file for 'qt5-speech'
       pkgname=qt5-speech
       version=5.15.7
      -revision=2
      +revision=3
       _commit=d32f4a479d38a11f547598004b975f4356424a16
       build_style=qmake
       configure_args="-- -flite -flite-alsa -speechd"
      
      From 652e89c8fc826c3a13c26a7624666bbe16f4cf4a Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Tue, 4 Apr 2023 18:38:50 -0400
      Subject: [PATCH 097/113] qt5-styleplugins: revbump for qt5-5.15.8
      
      ---
       srcpkgs/qt5-styleplugins/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/qt5-styleplugins/template b/srcpkgs/qt5-styleplugins/template
      index 96ed97d12cd2..30d93660a2a4 100644
      --- a/srcpkgs/qt5-styleplugins/template
      +++ b/srcpkgs/qt5-styleplugins/template
      @@ -1,7 +1,7 @@
       # Template file for 'qt5-styleplugins'
       pkgname=qt5-styleplugins
       version=5.0.0
      -revision=20
      +revision=21
       _gitrev=335dbece103e2cbf6c7cf819ab6672c2956b17b3
       build_style=qmake
       hostmakedepends="pkg-config qt5-host-tools qt5-qmake"
      
      From b8db05daa8125a247cd8c203c8a711a3447790ca Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Sun, 7 May 2023 20:14:14 -0400
      Subject: [PATCH 098/113] mlt7: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/gst-libav/template | 2 +-
       srcpkgs/mlt7/template      | 2 +-
       2 files changed, 2 insertions(+), 2 deletions(-)
      
      diff --git a/srcpkgs/gst-libav/template b/srcpkgs/gst-libav/template
      index 04c39bff1489..8c72fc3e97ee 100644
      --- a/srcpkgs/gst-libav/template
      +++ b/srcpkgs/gst-libav/template
      @@ -1,7 +1,7 @@
       # Template file for 'gst-libav'
       pkgname=gst-libav
       version=1.22.2
      -revision=2
      +revision=1
       build_style=meson
       hostmakedepends="pkg-config yasm"
       makedepends="orc-devel gst-plugins-base1-devel ffmpeg-devel"
      diff --git a/srcpkgs/mlt7/template b/srcpkgs/mlt7/template
      index 9fb7f60d692e..cca0eb68cfc3 100644
      --- a/srcpkgs/mlt7/template
      +++ b/srcpkgs/mlt7/template
      @@ -1,7 +1,7 @@
       # Template file for 'mlt7'
       pkgname=mlt7
       version=7.14.0
      -revision=1
      +revision=2
       build_style=cmake
       configure_args="-DSWIG_PYTHON=ON"
       hostmakedepends="doxygen pkg-config ladspa-sdk swig python3 which
      
      From 8d49b29b9ceab759ef3689f4bb3f8e58da79f99f Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Sun, 7 May 2023 20:15:03 -0400
      Subject: [PATCH 099/113] qt6-webengine: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/qt6-webengine/template | 3 ++-
       1 file changed, 2 insertions(+), 1 deletion(-)
      
      diff --git a/srcpkgs/qt6-webengine/template b/srcpkgs/qt6-webengine/template
      index 4e22cb6e8863..43778b568d3f 100644
      --- a/srcpkgs/qt6-webengine/template
      +++ b/srcpkgs/qt6-webengine/template
      @@ -1,7 +1,7 @@
       # Template file for 'qt6-webengine'
       pkgname=qt6-webengine
       version=6.5.0
      -revision=1
      +revision=2
       build_style=cmake
       configure_args="
        -DQT_FEATURE_webengine_system_ffmpeg=ON
      @@ -145,6 +145,7 @@ pre_install() {
       }
       
       post_install() {
      +	vlicense LICENSES/BSD-3-Clause.txt
       	local _file
       	find "${DESTDIR}"/usr/lib/qt6/examples \
       		-path '*/lib/qt6/**/lib/qt6/*' -type f |
      
      From a6f5b723228955d57cd68805809a878b5adf4e07 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Sun, 7 May 2023 20:15:29 -0400
      Subject: [PATCH 100/113] tracker-miners: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/tracker-miners/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/tracker-miners/template b/srcpkgs/tracker-miners/template
      index 8c005d697fa4..a6e5aa577702 100644
      --- a/srcpkgs/tracker-miners/template
      +++ b/srcpkgs/tracker-miners/template
      @@ -1,7 +1,7 @@
       # Template file for 'tracker-miners'
       pkgname=tracker-miners
       version=3.5.0
      -revision=3
      +revision=4
       build_style=meson
       build_helper=qemu
       # missing libgrss for miner_rss
      
      From 61039ebf953cf9299f310cd9efef436410ee2b8a Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Sun, 7 May 2023 20:20:58 -0400
      Subject: [PATCH 101/113] mpd: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/mpd/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/mpd/template b/srcpkgs/mpd/template
      index 9dbd4c935acc..9f058b62df2f 100644
      --- a/srcpkgs/mpd/template
      +++ b/srcpkgs/mpd/template
      @@ -1,7 +1,7 @@
       # Template file for 'mpd'
       pkgname=mpd
       version=0.23.13
      -revision=1
      +revision=2
       build_style=meson
       configure_args="-Dopus=enabled -Dmikmod=enabled -Dneighbor=true
        -Dsoundcloud=enabled -Dpipe=true -Dtwolame=enabled -Dbzip2=enabled
      
      From ac4662930dd7a1e5fb7bbb7613099172862c5e32 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Thu, 11 May 2023 14:05:14 -0400
      Subject: [PATCH 102/113] openmw: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/openmw/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/openmw/template b/srcpkgs/openmw/template
      index e3771c7aaf1a..3cbf20b06577 100644
      --- a/srcpkgs/openmw/template
      +++ b/srcpkgs/openmw/template
      @@ -1,7 +1,7 @@
       # Template file for 'openmw'
       pkgname=openmw
       version=0.47.0
      -revision=5
      +revision=6
       build_style=cmake
       _recast_commit=e75adf86f91eb3082220085e42dda62679f9a3ea
       _bullet_tag=3.17
      
      From 360b969af0ff30874d6bd75b5c494c779ca9a42c Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Sun, 21 May 2023 12:44:11 -0400
      Subject: [PATCH 103/113] electron24: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/electron24/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/electron24/template b/srcpkgs/electron24/template
      index bdaa56adc8a6..ff3d5e3ef381 100644
      --- a/srcpkgs/electron24/template
      +++ b/srcpkgs/electron24/template
      @@ -1,7 +1,7 @@
       # Template file for 'electron24'
       pkgname=electron24
       version=24.3.0
      -revision=1
      +revision=2
       _nodever=18.14.0
       _chromiumver=112.0.5615.165
       archs="x86_64* aarch64*"
      
      From faddb18286f1dc8ac8e0c8ac2ca81df604036f25 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Sat, 3 Jun 2023 08:20:22 -0400
      Subject: [PATCH 104/113] gtk4: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/gtk4/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/gtk4/template b/srcpkgs/gtk4/template
      index b318b7bae1dd..e3bde4a50e54 100644
      --- a/srcpkgs/gtk4/template
      +++ b/srcpkgs/gtk4/template
      @@ -1,7 +1,7 @@
       # Template file for 'gtk4'
       pkgname=gtk4
       version=4.10.4
      -revision=1
      +revision=2
       build_style=meson
       build_helper="gir"
       configure_args="-Dman-pages=true -Dgtk_doc=true -Dbuild-tests=false
      
      From 09f99f2f3ea510c4b14b154329e6aa37ec144b48 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Sun, 4 Jun 2023 11:25:50 -0400
      Subject: [PATCH 105/113] electron19: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/electron19/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/electron19/template b/srcpkgs/electron19/template
      index 32ce301e730c..ab7f308f5e8a 100644
      --- a/srcpkgs/electron19/template
      +++ b/srcpkgs/electron19/template
      @@ -1,7 +1,7 @@
       # Template file for 'electron19'
       pkgname=electron19
       version=19.0.8
      -revision=3
      +revision=4
       _nodever=16.14.2
       _chromiumver=102.0.5005.125
       archs="x86_64* aarch64* ppc64le*"
      
      From 8174e587b45289a2e54b8d41792e47a0c16acbea Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Sun, 4 Jun 2023 11:28:26 -0400
      Subject: [PATCH 106/113] siril: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/siril/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/siril/template b/srcpkgs/siril/template
      index 84332f79d060..62750dd24754 100644
      --- a/srcpkgs/siril/template
      +++ b/srcpkgs/siril/template
      @@ -1,7 +1,7 @@
       # Template file for 'siril'
       pkgname=siril
       version=0.9.12
      -revision=10
      +revision=11
       build_style=gnu-configure
       hostmakedepends="pkg-config intltool autoconf automake gettext-devel"
       makedepends="fftw-devel libconfig-devel libopencv-devel libffms2-devel
      
      From 5d65dda3eaf41a73c77b42fdd076edec444f55f1 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Sun, 4 Jun 2023 11:29:08 -0400
      Subject: [PATCH 107/113] telegram-desktop: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/telegram-desktop/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/telegram-desktop/template b/srcpkgs/telegram-desktop/template
      index f114b2341dc5..9db9f80c1a53 100644
      --- a/srcpkgs/telegram-desktop/template
      +++ b/srcpkgs/telegram-desktop/template
      @@ -1,7 +1,7 @@
       # Template file for 'telegram-desktop'
       pkgname=telegram-desktop
       version=4.8.1
      -revision=3
      +revision=4
       build_style=cmake
       build_helper="qemu"
       configure_args="-DTDESKTOP_API_ID=209235
      
      From 0621ab4b4ce9ae1c549c50e9c4184a4ccb8ba12d Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Sat, 10 Jun 2023 00:40:39 -0400
      Subject: [PATCH 108/113] freecad: revbump for qt5-webengine-5.15.13
      
      ---
       srcpkgs/freecad/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/freecad/template b/srcpkgs/freecad/template
      index a4a3f5f76b29..8608d1670c87 100644
      --- a/srcpkgs/freecad/template
      +++ b/srcpkgs/freecad/template
      @@ -1,7 +1,7 @@
       # Template file for 'freecad'
       pkgname=freecad
       version=0.20.2
      -revision=5
      +revision=6
       build_style=cmake
       
       _inst_prefix=/usr/lib/${pkgname}
      
      From 3e9bdeea13f55fe8999fedce9ea52e72dff8dfc7 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Sat, 10 Jun 2023 00:57:09 -0400
      Subject: [PATCH 109/113] qt6-multimedia: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/qt6-multimedia/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/qt6-multimedia/template b/srcpkgs/qt6-multimedia/template
      index a6832fdd69bf..c9ffac914ab8 100644
      --- a/srcpkgs/qt6-multimedia/template
      +++ b/srcpkgs/qt6-multimedia/template
      @@ -1,7 +1,7 @@
       # Template file for 'qt6-multimedia'
       pkgname=qt6-multimedia
       version=6.5.0
      -revision=2
      +revision=3
       build_style=cmake
       configure_args="-DQT_FEATURE_gstreamer=ON"
       hostmakedepends="perl qt6-declarative-host-tools pkg-config qt6-shadertools"
      
      From e431082ec2d089ef95b916a542b3288af4f18884 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Thu, 22 Jun 2023 10:25:02 -0400
      Subject: [PATCH 110/113] kdenlive: revbump for ffmpeg-6.0
      
      ---
       srcpkgs/kdenlive/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/kdenlive/template b/srcpkgs/kdenlive/template
      index 89c0dcfb8577..75495b3a3586 100644
      --- a/srcpkgs/kdenlive/template
      +++ b/srcpkgs/kdenlive/template
      @@ -1,7 +1,7 @@
       # Template file for 'kdenlive'
       pkgname=kdenlive
       version=23.04.2
      -revision=2
      +revision=3
       build_style=cmake
       hostmakedepends="
        extra-cmake-modules kconfig kcoreaddons kdoctools pkg-config python3
      
      From 28908f16b61797cef5c47f92a5fb7fe8b097f92b Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Tue, 4 Jul 2023 09:18:23 -0400
      Subject: [PATCH 111/113] gmic: revbump for opencv-4.7.0
      
      ---
       srcpkgs/gmic/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/gmic/template b/srcpkgs/gmic/template
      index 0bb4034d5cc8..808953e9b543 100644
      --- a/srcpkgs/gmic/template
      +++ b/srcpkgs/gmic/template
      @@ -1,7 +1,7 @@
       # Template file for 'gmic'
       pkgname=gmic
       version=3.1.6
      -revision=4
      +revision=5
       _zart_hash=34ebf6cce0bafb98abe57cec83c4a02cd1abeca0
       create_wrksrc=yes
       build_wrksrc="src"
      
      From 6427f55e166b1c3a8a79cb59624e5d2d25c529b5 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Tue, 4 Jul 2023 09:29:52 -0400
      Subject: [PATCH 112/113] synfigstudio: revbump for synfig mlt7
      
      ---
       srcpkgs/synfigstudio/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/synfigstudio/template b/srcpkgs/synfigstudio/template
      index af1c5a296ef0..09e442da9a68 100644
      --- a/srcpkgs/synfigstudio/template
      +++ b/srcpkgs/synfigstudio/template
      @@ -2,7 +2,7 @@
       # Should be kept in sync with 'synfig' and 'ETL'
       pkgname=synfigstudio
       version=1.4.4
      -revision=3
      +revision=4
       build_style=gnu-configure
       configure_args="--disable-update-mimedb"
       hostmakedepends="pkg-config intltool gettext synfig"
      
      From e2ae58981344c6169a0c33839896c545abdefc86 Mon Sep 17 00:00:00 2001
      From: zlice 
      Date: Tue, 4 Jul 2023 10:19:17 -0400
      Subject: [PATCH 113/113] openimageio: revbump for ffmpeg6.0
      
      ---
       srcpkgs/openimageio/template | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/srcpkgs/openimageio/template b/srcpkgs/openimageio/template
      index 0e9e22e9685d..e74a8dbd683e 100644
      --- a/srcpkgs/openimageio/template
      +++ b/srcpkgs/openimageio/template
      @@ -1,7 +1,7 @@
       # Template file for 'openimageio'
       pkgname=openimageio
       version=2.4.9.0
      -revision=5
      +revision=6
       build_style=cmake
       build_helper=qemu
       configure_args="-DUSE_QT=0 -DUSE_PYTHON=0 -DOIIO_BUILD_TESTS=0