summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/3rdparty/libpng/ANNOUNCE47
-rw-r--r--src/3rdparty/libpng/CHANGES26
-rw-r--r--src/3rdparty/libpng/README2
-rw-r--r--src/3rdparty/libpng/libpng-manual.txt15
-rw-r--r--src/3rdparty/libpng/png.c20
-rw-r--r--src/3rdparty/libpng/png.h14
-rw-r--r--src/3rdparty/libpng/pngconf.h2
-rw-r--r--src/3rdparty/libpng/pngdebug.h3
-rw-r--r--src/3rdparty/libpng/pngerror.c138
-rw-r--r--src/3rdparty/libpng/pnglibconf.h2
-rw-r--r--src/3rdparty/libpng/pngpriv.h10
-rw-r--r--src/3rdparty/libpng/pngread.c75
-rw-r--r--src/3rdparty/libpng/pngrtran.c114
-rw-r--r--src/3rdparty/libpng/pngstruct.h1
-rw-r--r--src/3rdparty/libpng/pngwrite.c3
-rw-r--r--src/3rdparty/libpng/qt_attribution.json4
-rw-r--r--src/corelib/CMakeLists.txt1
-rw-r--r--src/corelib/animation/qabstractanimation.cpp4
-rw-r--r--src/corelib/animation/qabstractanimation_p.h8
-rw-r--r--src/corelib/platform/wasm/qwasmanimationdriver.cpp129
-rw-r--r--src/corelib/platform/wasm/qwasmanimationdriver_p.h54
-rw-r--r--src/corelib/platform/wasm/qwasmsuspendresumecontrol.cpp132
-rw-r--r--src/corelib/platform/wasm/qwasmsuspendresumecontrol_p.h33
-rw-r--r--src/corelib/tools/qcryptographichash.cpp2
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp14
-rw-r--r--src/network/socket/qabstractsocket.cpp39
-rw-r--r--src/network/socket/qabstractsocket.h5
-rw-r--r--src/network/socket/qabstractsocketengine_p.h3
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp24
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp21
-rw-r--r--src/plugins/platforms/cocoa/qnsview_mouse.mm3
-rw-r--r--src/plugins/platforms/direct2d/CMakeLists.txt1
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.cpp43
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.h16
-rw-r--r--src/plugins/platforms/windows/CMakeLists.txt1
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowssystemtrayicon.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowswindowclassdescription.cpp78
-rw-r--r--src/plugins/platforms/windows/qwindowswindowclassdescription.h30
-rw-r--r--src/plugins/platforms/windows/qwindowswindowclassregistry.cpp114
-rw-r--r--src/plugins/platforms/windows/qwindowswindowclassregistry.h10
-rw-r--r--src/widgets/widgets/qwidgetanimator.cpp5
-rw-r--r--tests/auto/corelib/platform/android/tst_android.cpp11
-rw-r--r--tests/auto/gui/kernel/qguieventdispatcher/BLACKLIST2
-rw-r--r--tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.cpp8
48 files changed, 882 insertions, 405 deletions
diff --git a/src/3rdparty/libpng/ANNOUNCE b/src/3rdparty/libpng/ANNOUNCE
index 516e078082d..ae0b6ccc13b 100644
--- a/src/3rdparty/libpng/ANNOUNCE
+++ b/src/3rdparty/libpng/ANNOUNCE
@@ -1,5 +1,5 @@
-libpng 1.6.50 - July 1, 2025
-============================
+libpng 1.6.51 - November 21, 2025
+=================================
This is a public release of libpng, intended for use in production code.
@@ -9,13 +9,13 @@ Files available for download
Source files with LF line endings (for Unix/Linux):
- * libpng-1.6.50.tar.xz (LZMA-compressed, recommended)
- * libpng-1.6.50.tar.gz (deflate-compressed)
+ * libpng-1.6.51.tar.xz (LZMA-compressed, recommended)
+ * libpng-1.6.51.tar.gz (deflate-compressed)
Source files with CRLF line endings (for Windows):
- * lpng1650.7z (LZMA-compressed, recommended)
- * lpng1650.zip (deflate-compressed)
+ * lpng1651.7z (LZMA-compressed, recommended)
+ * lpng1651.zip (deflate-compressed)
Other information:
@@ -25,18 +25,33 @@ Other information:
* TRADEMARK.md
-Changes from version 1.6.49 to version 1.6.50
+Changes from version 1.6.50 to version 1.6.51
---------------------------------------------
- * Improved the detection of the RVV Extension on the RISC-V platform.
- (Contributed by Filip Wasil)
- * Replaced inline ASM with C intrinsics in the RVV code.
- (Contributed by Filip Wasil)
- * Fixed a decoder defect in which unknown chunks trailing IDAT, set
- to go through the unknown chunk handler, incorrectly triggered
- out-of-place IEND errors.
- (Contributed by John Bowler)
- * Fixed the CMake file for cross-platform builds that require `libm`.
+ * Fixed CVE-2025-64505 (moderate severity):
+ Heap buffer overflow in `png_do_quantize` via malformed palette index.
+ (Reported by Samsung; analyzed by Fabio Gritti.)
+ * Fixed CVE-2025-64506 (moderate severity):
+ Heap buffer over-read in `png_write_image_8bit` with 8-bit input and
+ `convert_to_8bit` enabled.
+ (Reported by Samsung and <weijinjinnihao@users.noreply.github.com>;
+ analyzed by Fabio Gritti.)
+ * Fixed CVE-2025-64720 (high severity):
+ Buffer overflow in `png_image_read_composite` via incorrect palette
+ premultiplication.
+ (Reported by Samsung; analyzed by John Bowler.)
+ * Fixed CVE-2025-65018 (high severity):
+ Heap buffer overflow in `png_combine_row` triggered via
+ `png_image_finish_read`.
+ (Reported by <yosiimich@users.noreply.github.com>.)
+ * Fixed a memory leak in `png_set_quantize`.
+ (Reported by Samsung; analyzed by Fabio Gritti.)
+ * Removed the experimental and incomplete ERROR_NUMBERS code.
+ (Contributed by Tobias Stoeckmann.)
+ * Improved the RISC-V vector extension support; required RVV 1.0 or newer.
+ (Contributed by Filip Wasil.)
+ * Added GitHub Actions workflows for automated testing.
+ * Performed various refactorings and cleanups.
Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
diff --git a/src/3rdparty/libpng/CHANGES b/src/3rdparty/libpng/CHANGES
index b6499b1f34c..2478fd0fc08 100644
--- a/src/3rdparty/libpng/CHANGES
+++ b/src/3rdparty/libpng/CHANGES
@@ -6278,6 +6278,32 @@ Version 1.6.50 [July 1, 2025]
(Contributed by John Bowler)
Fixed the CMake file for cross-platform builds that require `libm`.
+Version 1.6.51 [November 21, 2025]
+ Fixed CVE-2025-64505 (moderate severity):
+ Heap buffer overflow in `png_do_quantize` via malformed palette index.
+ (Reported by Samsung; analyzed by Fabio Gritti.)
+ Fixed CVE-2025-64506 (moderate severity):
+ Heap buffer over-read in `png_write_image_8bit` with 8-bit input and
+ `convert_to_8bit` enabled.
+ (Reported by Samsung and <weijinjinnihao@users.noreply.github.com>;
+ analyzed by Fabio Gritti.)
+ Fixed CVE-2025-64720 (high severity):
+ Buffer overflow in `png_image_read_composite` via incorrect palette
+ premultiplication.
+ (Reported by Samsung; analyzed by John Bowler.)
+ Fixed CVE-2025-65018 (high severity):
+ Heap buffer overflow in `png_combine_row` triggered via
+ `png_image_finish_read`.
+ (Reported by <yosiimich@users.noreply.github.com>.)
+ Fixed a memory leak in `png_set_quantize`.
+ (Reported by Samsung; analyzed by Fabio Gritti.)
+ Removed the experimental and incomplete ERROR_NUMBERS code.
+ (Contributed by Tobias Stoeckmann.)
+ Improved the RISC-V vector extension support; required RVV 1.0 or newer.
+ (Contributed by Filip Wasil.)
+ Added GitHub Actions workflows for automated testing.
+ Performed various refactorings and cleanups.
+
Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
Subscription is required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
diff --git a/src/3rdparty/libpng/README b/src/3rdparty/libpng/README
index 2eb633ac0fb..5ea329ee3da 100644
--- a/src/3rdparty/libpng/README
+++ b/src/3rdparty/libpng/README
@@ -1,4 +1,4 @@
-README for libpng version 1.6.50
+README for libpng version 1.6.51
================================
See the note about version numbers near the top of `png.h`.
diff --git a/src/3rdparty/libpng/libpng-manual.txt b/src/3rdparty/libpng/libpng-manual.txt
index 6c07e1022b6..f342c18e814 100644
--- a/src/3rdparty/libpng/libpng-manual.txt
+++ b/src/3rdparty/libpng/libpng-manual.txt
@@ -9,7 +9,7 @@ libpng-manual.txt - A description on how to use and modify libpng
Based on:
- libpng version 1.6.36, December 2018, through 1.6.50 - July 2025
+ libpng version 1.6.36, December 2018, through 1.6.51 - November 2025
Updated and distributed by Cosmin Truta
Copyright (c) 2018-2025 Cosmin Truta
@@ -3355,19 +3355,6 @@ Here is an example of writing two private chunks, prVt and miNE:
/* Needed because miNE is not safe-to-copy */
png_set_keep_unknown_chunks(png, PNG_HANDLE_CHUNK_ALWAYS,
(png_bytep) "miNE", 1);
- # if PNG_LIBPNG_VER < 10600
- /* Deal with unknown chunk location bug in 1.5.x and earlier */
- png_set_unknown_chunk_location(png, info, 0, PNG_HAVE_IHDR);
- png_set_unknown_chunk_location(png, info, 1, PNG_AFTER_IDAT);
- # endif
- # if PNG_LIBPNG_VER < 10500
- /* PNG_AFTER_IDAT writes two copies of the chunk prior to libpng-1.5.0,
- * one before IDAT and another after IDAT, so don't use it; only use
- * PNG_HAVE_IHDR location. This call resets the location previously
- * set by assignment and png_set_unknown_chunk_location() for chunk 1.
- */
- png_set_unknown_chunk_location(png, info, 1, PNG_HAVE_IHDR);
- # endif
#endif
The high-level write interface
diff --git a/src/3rdparty/libpng/png.c b/src/3rdparty/libpng/png.c
index 6e21915c402..380c4c19e6a 100644
--- a/src/3rdparty/libpng/png.c
+++ b/src/3rdparty/libpng/png.c
@@ -13,7 +13,7 @@
#include "pngpriv.h"
/* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_50 Your_png_h_is_not_version_1_6_50;
+typedef png_libpng_version_1_6_51 Your_png_h_is_not_version_1_6_51;
/* Sanity check the chunks definitions - PNG_KNOWN_CHUNKS from pngpriv.h and the
* corresponding macro definitions. This causes a compile time failure if
@@ -108,10 +108,16 @@ png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED)
if (png_ptr == NULL)
return NULL;
- if (items >= (~(png_alloc_size_t)0)/size)
+ /* This check against overflow is vestigial, dating back from
+ * the old times when png_zalloc used to be an exported function.
+ * We're still keeping it here for now, as an extra-cautious
+ * prevention against programming errors inside zlib, although it
+ * should rather be a debug-time assertion instead.
+ */
+ if (size != 0 && items >= (~(png_alloc_size_t)0) / size)
{
- png_warning (png_voidcast(png_structrp, png_ptr),
- "Potential overflow in png_zalloc()");
+ png_warning(png_voidcast(png_structrp, png_ptr),
+ "Potential overflow in png_zalloc()");
return NULL;
}
@@ -238,10 +244,6 @@ png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver)
png_warning(png_ptr, m);
#endif
-#ifdef PNG_ERROR_NUMBERS_SUPPORTED
- png_ptr->flags = 0;
-#endif
-
return 0;
}
@@ -815,7 +817,7 @@ png_get_copyright(png_const_structrp png_ptr)
return PNG_STRING_COPYRIGHT
#else
return PNG_STRING_NEWLINE \
- "libpng version 1.6.50" PNG_STRING_NEWLINE \
+ "libpng version 1.6.51" PNG_STRING_NEWLINE \
"Copyright (c) 2018-2025 Cosmin Truta" PNG_STRING_NEWLINE \
"Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
PNG_STRING_NEWLINE \
diff --git a/src/3rdparty/libpng/png.h b/src/3rdparty/libpng/png.h
index b9985e81680..fb93d2242b5 100644
--- a/src/3rdparty/libpng/png.h
+++ b/src/3rdparty/libpng/png.h
@@ -1,6 +1,6 @@
/* png.h - header file for PNG reference library
*
- * libpng version 1.6.50
+ * libpng version 1.6.51
*
* Copyright (c) 2018-2025 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
@@ -14,7 +14,7 @@
* libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
* libpng versions 0.97, January 1998, through 1.6.35, July 2018:
* Glenn Randers-Pehrson
- * libpng versions 1.6.36, December 2018, through 1.6.50, July 2025:
+ * libpng versions 1.6.36, December 2018, through 1.6.51, November 2025:
* Cosmin Truta
* See also "Contributing Authors", below.
*/
@@ -238,7 +238,7 @@
* ...
* 1.5.30 15 10530 15.so.15.30[.0]
* ...
- * 1.6.50 16 10650 16.so.16.50[.0]
+ * 1.6.51 16 10651 16.so.16.51[.0]
*
* Henceforth the source version will match the shared-library major and
* minor numbers; the shared-library major version number will be used for
@@ -274,7 +274,7 @@
*/
/* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.50"
+#define PNG_LIBPNG_VER_STRING "1.6.51"
#define PNG_HEADER_VERSION_STRING " libpng version " PNG_LIBPNG_VER_STRING "\n"
/* The versions of shared library builds should stay in sync, going forward */
@@ -285,7 +285,7 @@
/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
#define PNG_LIBPNG_VER_MAJOR 1
#define PNG_LIBPNG_VER_MINOR 6
-#define PNG_LIBPNG_VER_RELEASE 50
+#define PNG_LIBPNG_VER_RELEASE 51
/* This should be zero for a public release, or non-zero for a
* development version.
@@ -316,7 +316,7 @@
* From version 1.0.1 it is:
* XXYYZZ, where XX=major, YY=minor, ZZ=release
*/
-#define PNG_LIBPNG_VER 10650 /* 1.6.50 */
+#define PNG_LIBPNG_VER 10651 /* 1.6.51 */
/* Library configuration: these options cannot be changed after
* the library has been built.
@@ -426,7 +426,7 @@ extern "C" {
/* This triggers a compiler error in png.c, if png.c and png.h
* do not agree upon the version number.
*/
-typedef char* png_libpng_version_1_6_50;
+typedef char* png_libpng_version_1_6_51;
/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
*
diff --git a/src/3rdparty/libpng/pngconf.h b/src/3rdparty/libpng/pngconf.h
index d1081b54ddd..981df68d87a 100644
--- a/src/3rdparty/libpng/pngconf.h
+++ b/src/3rdparty/libpng/pngconf.h
@@ -1,6 +1,6 @@
/* pngconf.h - machine-configurable file for libpng
*
- * libpng version 1.6.50
+ * libpng version 1.6.51
*
* Copyright (c) 2018-2025 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
diff --git a/src/3rdparty/libpng/pngdebug.h b/src/3rdparty/libpng/pngdebug.h
index af1ae9e8212..0337918aec3 100644
--- a/src/3rdparty/libpng/pngdebug.h
+++ b/src/3rdparty/libpng/pngdebug.h
@@ -38,9 +38,6 @@
#define PNGDEBUG_H
/* These settings control the formatting of messages in png.c and pngerror.c */
/* Moved to pngdebug.h at 1.5.0 */
-# ifndef PNG_LITERAL_SHARP
-# define PNG_LITERAL_SHARP 0x23
-# endif
# ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET
# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b
# endif
diff --git a/src/3rdparty/libpng/pngerror.c b/src/3rdparty/libpng/pngerror.c
index 01a7ef5347e..044fa2eb68c 100644
--- a/src/3rdparty/libpng/pngerror.c
+++ b/src/3rdparty/libpng/pngerror.c
@@ -39,46 +39,6 @@ PNG_FUNCTION(void,PNGAPI
png_error,(png_const_structrp png_ptr, png_const_charp error_message),
PNG_NORETURN)
{
-#ifdef PNG_ERROR_NUMBERS_SUPPORTED
- char msg[16];
- if (png_ptr != NULL)
- {
- if ((png_ptr->flags &
- (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
- {
- if (*error_message == PNG_LITERAL_SHARP)
- {
- /* Strip "#nnnn " from beginning of error message. */
- int offset;
- for (offset = 1; offset<15; offset++)
- if (error_message[offset] == ' ')
- break;
-
- if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
- {
- int i;
- for (i = 0; i < offset - 1; i++)
- msg[i] = error_message[i + 1];
- msg[i - 1] = '\0';
- error_message = msg;
- }
-
- else
- error_message += offset;
- }
-
- else
- {
- if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
- {
- msg[0] = '0';
- msg[1] = '\0';
- error_message = msg;
- }
- }
- }
- }
-#endif
if (png_ptr != NULL && png_ptr->error_fn != NULL)
(*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr),
error_message);
@@ -216,21 +176,6 @@ void PNGAPI
png_warning(png_const_structrp png_ptr, png_const_charp warning_message)
{
int offset = 0;
- if (png_ptr != NULL)
- {
-#ifdef PNG_ERROR_NUMBERS_SUPPORTED
- if ((png_ptr->flags &
- (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
-#endif
- {
- if (*warning_message == PNG_LITERAL_SHARP)
- {
- for (offset = 1; offset < 15; offset++)
- if (warning_message[offset] == ' ')
- break;
- }
- }
- }
if (png_ptr != NULL && png_ptr->warning_fn != NULL)
(*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr),
warning_message + offset);
@@ -712,42 +657,9 @@ png_default_error,(png_const_structrp png_ptr, png_const_charp error_message),
PNG_NORETURN)
{
#ifdef PNG_CONSOLE_IO_SUPPORTED
-#ifdef PNG_ERROR_NUMBERS_SUPPORTED
- /* Check on NULL only added in 1.5.4 */
- if (error_message != NULL && *error_message == PNG_LITERAL_SHARP)
- {
- /* Strip "#nnnn " from beginning of error message. */
- int offset;
- char error_number[16];
- for (offset = 0; offset<15; offset++)
- {
- error_number[offset] = error_message[offset + 1];
- if (error_message[offset] == ' ')
- break;
- }
-
- if ((offset > 1) && (offset < 15))
- {
- error_number[offset - 1] = '\0';
- fprintf(stderr, "libpng error no. %s: %s",
- error_number, error_message + offset + 1);
- fprintf(stderr, PNG_STRING_NEWLINE);
- }
-
- else
- {
- fprintf(stderr, "libpng error: %s, offset=%d",
- error_message, offset);
- fprintf(stderr, PNG_STRING_NEWLINE);
- }
- }
- else
-#endif
- {
- fprintf(stderr, "libpng error: %s", error_message ? error_message :
- "undefined");
- fprintf(stderr, PNG_STRING_NEWLINE);
- }
+ fprintf(stderr, "libpng error: %s", error_message ? error_message :
+ "undefined");
+ fprintf(stderr, PNG_STRING_NEWLINE);
#else
PNG_UNUSED(error_message) /* Make compiler happy */
#endif
@@ -785,40 +697,8 @@ static void /* PRIVATE */
png_default_warning(png_const_structrp png_ptr, png_const_charp warning_message)
{
#ifdef PNG_CONSOLE_IO_SUPPORTED
-# ifdef PNG_ERROR_NUMBERS_SUPPORTED
- if (*warning_message == PNG_LITERAL_SHARP)
- {
- int offset;
- char warning_number[16];
- for (offset = 0; offset < 15; offset++)
- {
- warning_number[offset] = warning_message[offset + 1];
- if (warning_message[offset] == ' ')
- break;
- }
-
- if ((offset > 1) && (offset < 15))
- {
- warning_number[offset + 1] = '\0';
- fprintf(stderr, "libpng warning no. %s: %s",
- warning_number, warning_message + offset);
- fprintf(stderr, PNG_STRING_NEWLINE);
- }
-
- else
- {
- fprintf(stderr, "libpng warning: %s",
- warning_message);
- fprintf(stderr, PNG_STRING_NEWLINE);
- }
- }
- else
-# endif
-
- {
- fprintf(stderr, "libpng warning: %s", warning_message);
- fprintf(stderr, PNG_STRING_NEWLINE);
- }
+ fprintf(stderr, "libpng warning: %s", warning_message);
+ fprintf(stderr, PNG_STRING_NEWLINE);
#else
PNG_UNUSED(warning_message) /* Make compiler happy */
#endif
@@ -866,12 +746,8 @@ png_get_error_ptr(png_const_structrp png_ptr)
void PNGAPI
png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode)
{
- if (png_ptr != NULL)
- {
- png_ptr->flags &=
- ((~(PNG_FLAG_STRIP_ERROR_NUMBERS |
- PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode);
- }
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(strip_mode)
}
#endif
diff --git a/src/3rdparty/libpng/pnglibconf.h b/src/3rdparty/libpng/pnglibconf.h
index f15fc16dade..00432d6c033 100644
--- a/src/3rdparty/libpng/pnglibconf.h
+++ b/src/3rdparty/libpng/pnglibconf.h
@@ -1,6 +1,6 @@
/* pnglibconf.h - library build configuration */
-/* libpng version 1.6.50 */
+/* libpng version 1.6.51 */
/* Copyright (c) 2018-2025 Cosmin Truta */
/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */
diff --git a/src/3rdparty/libpng/pngpriv.h b/src/3rdparty/libpng/pngpriv.h
index e3054b90aae..fc8d461cf5f 100644
--- a/src/3rdparty/libpng/pngpriv.h
+++ b/src/3rdparty/libpng/pngpriv.h
@@ -302,7 +302,7 @@
# define PNG_LOONGARCH_LSX_IMPLEMENTATION 0
#endif
-#if PNG_RISCV_RVV_OPT > 0
+#if PNG_RISCV_RVV_OPT > 0 && __riscv_v >= 1000000
# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_rvv
# ifndef PNG_RISCV_RVV_IMPLEMENTATION
/* Use the intrinsics code by default. */
@@ -310,7 +310,7 @@
# endif
#else
# define PNG_RISCV_RVV_IMPLEMENTATION 0
-#endif
+#endif /* PNG_RISCV_RVV_OPT > 0 && __riscv_v >= 1000000 */
/* Is this a build of a DLL where compilation of the object modules requires
* different preprocessor settings to those required for a simple library? If
@@ -710,7 +710,7 @@
/* #define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000U */
/* #define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000U */
#define PNG_FLAG_LIBRARY_MISMATCH 0x20000U
-#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000U
+ /* 0x40000U unused */
#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000U
#define PNG_FLAG_BENIGN_ERRORS_WARN 0x100000U /* Added to libpng-1.4.0 */
#define PNG_FLAG_APP_WARNINGS_WARN 0x200000U /* Added to libpng-1.6.0 */
@@ -1546,7 +1546,7 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_lsx,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
#endif
-#if PNG_RISCV_RVV_OPT > 0
+#if PNG_RISCV_RVV_IMPLEMENTATION == 1
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_rvv,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_rvv,(png_row_infop
@@ -2175,7 +2175,7 @@ PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_lsx,
(png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
#endif
-# if PNG_RISCV_RVV_OPT > 0
+# if PNG_RISCV_RVV_IMPLEMENTATION == 1
PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_rvv,
(png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
#endif
diff --git a/src/3rdparty/libpng/pngread.c b/src/3rdparty/libpng/pngread.c
index 212afb7d215..79917daaaf9 100644
--- a/src/3rdparty/libpng/pngread.c
+++ b/src/3rdparty/libpng/pngread.c
@@ -3129,6 +3129,54 @@ png_image_read_colormapped(png_voidp argument)
}
}
+/* Row reading for interlaced 16-to-8 bit depth conversion with local buffer. */
+static int
+png_image_read_direct_scaled(png_voidp argument)
+{
+ png_image_read_control *display = png_voidcast(png_image_read_control*,
+ argument);
+ png_imagep image = display->image;
+ png_structrp png_ptr = image->opaque->png_ptr;
+ png_bytep local_row = png_voidcast(png_bytep, display->local_row);
+ png_bytep first_row = png_voidcast(png_bytep, display->first_row);
+ ptrdiff_t row_bytes = display->row_bytes;
+ int passes;
+
+ /* Handle interlacing. */
+ switch (png_ptr->interlaced)
+ {
+ case PNG_INTERLACE_NONE:
+ passes = 1;
+ break;
+
+ case PNG_INTERLACE_ADAM7:
+ passes = PNG_INTERLACE_ADAM7_PASSES;
+ break;
+
+ default:
+ png_error(png_ptr, "unknown interlace type");
+ }
+
+ /* Read each pass using local_row as intermediate buffer. */
+ while (--passes >= 0)
+ {
+ png_uint_32 y = image->height;
+ png_bytep output_row = first_row;
+
+ for (; y > 0; --y)
+ {
+ /* Read into local_row (gets transformed 8-bit data). */
+ png_read_row(png_ptr, local_row, NULL);
+
+ /* Copy from local_row to user buffer. */
+ memcpy(output_row, local_row, (size_t)row_bytes);
+ output_row += row_bytes;
+ }
+ }
+
+ return 1;
+}
+
/* Just the row reading part of png_image_read. */
static int
png_image_read_composite(png_voidp argument)
@@ -3547,6 +3595,7 @@ png_image_read_direct(png_voidp argument)
int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0;
int do_local_compose = 0;
int do_local_background = 0; /* to avoid double gamma correction bug */
+ int do_local_scale = 0; /* for interlaced 16-to-8 bit conversion */
int passes = 0;
/* Add transforms to ensure the correct output format is produced then check
@@ -3680,8 +3729,16 @@ png_image_read_direct(png_voidp argument)
png_set_expand_16(png_ptr);
else /* 8-bit output */
+ {
png_set_scale_16(png_ptr);
+ /* For interlaced images, use local_row buffer to avoid overflow
+ * in png_combine_row() which writes using IHDR bit-depth.
+ */
+ if (png_ptr->interlaced != 0)
+ do_local_scale = 1;
+ }
+
change &= ~PNG_FORMAT_FLAG_LINEAR;
}
@@ -3957,6 +4014,24 @@ png_image_read_direct(png_voidp argument)
return result;
}
+ else if (do_local_scale != 0)
+ {
+ /* For interlaced 16-to-8 conversion, use an intermediate row buffer
+ * to avoid buffer overflows in png_combine_row. The local_row is sized
+ * for the transformed (8-bit) output, preventing the overflow that would
+ * occur if png_combine_row wrote 16-bit data directly to the user buffer.
+ */
+ int result;
+ png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
+
+ display->local_row = row;
+ result = png_safe_execute(image, png_image_read_direct_scaled, display);
+ display->local_row = NULL;
+ png_free(png_ptr, row);
+
+ return result;
+ }
+
else
{
png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes;
diff --git a/src/3rdparty/libpng/pngrtran.c b/src/3rdparty/libpng/pngrtran.c
index 1809db70473..2f520225515 100644
--- a/src/3rdparty/libpng/pngrtran.c
+++ b/src/3rdparty/libpng/pngrtran.c
@@ -501,9 +501,19 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
{
int i;
+ /* Initialize the array to index colors.
+ *
+ * Ensure quantize_index can fit 256 elements (PNG_MAX_PALETTE_LENGTH)
+ * rather than num_palette elements. This is to prevent buffer overflows
+ * caused by malformed PNG files with out-of-range palette indices.
+ *
+ * Be careful to avoid leaking memory. Applications are allowed to call
+ * this function more than once per png_struct.
+ */
+ png_free(png_ptr, png_ptr->quantize_index);
png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
- (png_alloc_size_t)num_palette);
- for (i = 0; i < num_palette; i++)
+ PNG_MAX_PALETTE_LENGTH);
+ for (i = 0; i < PNG_MAX_PALETTE_LENGTH; i++)
png_ptr->quantize_index[i] = (png_byte)i;
}
@@ -515,15 +525,14 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
* Perhaps not the best solution, but good enough.
*/
- int i;
+ png_bytep quantize_sort;
+ int i, j;
- /* Initialize an array to sort colors */
- png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
+ /* Initialize the local array to sort colors. */
+ quantize_sort = (png_bytep)png_malloc(png_ptr,
(png_alloc_size_t)num_palette);
-
- /* Initialize the quantize_sort array */
for (i = 0; i < num_palette; i++)
- png_ptr->quantize_sort[i] = (png_byte)i;
+ quantize_sort[i] = (png_byte)i;
/* Find the least used palette entries by starting a
* bubble sort, and running it until we have sorted
@@ -535,19 +544,18 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
for (i = num_palette - 1; i >= maximum_colors; i--)
{
int done; /* To stop early if the list is pre-sorted */
- int j;
done = 1;
for (j = 0; j < i; j++)
{
- if (histogram[png_ptr->quantize_sort[j]]
- < histogram[png_ptr->quantize_sort[j + 1]])
+ if (histogram[quantize_sort[j]]
+ < histogram[quantize_sort[j + 1]])
{
png_byte t;
- t = png_ptr->quantize_sort[j];
- png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1];
- png_ptr->quantize_sort[j + 1] = t;
+ t = quantize_sort[j];
+ quantize_sort[j] = quantize_sort[j + 1];
+ quantize_sort[j + 1] = t;
done = 0;
}
}
@@ -559,18 +567,18 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
/* Swap the palette around, and set up a table, if necessary */
if (full_quantize != 0)
{
- int j = num_palette;
+ j = num_palette;
/* Put all the useful colors within the max, but don't
* move the others.
*/
for (i = 0; i < maximum_colors; i++)
{
- if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
+ if ((int)quantize_sort[i] >= maximum_colors)
{
do
j--;
- while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
+ while ((int)quantize_sort[j] >= maximum_colors);
palette[i] = palette[j];
}
@@ -578,7 +586,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
}
else
{
- int j = num_palette;
+ j = num_palette;
/* Move all the used colors inside the max limit, and
* develop a translation table.
@@ -586,13 +594,13 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
for (i = 0; i < maximum_colors; i++)
{
/* Only move the colors we need to */
- if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
+ if ((int)quantize_sort[i] >= maximum_colors)
{
png_color tmp_color;
do
j--;
- while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
+ while ((int)quantize_sort[j] >= maximum_colors);
tmp_color = palette[j];
palette[j] = palette[i];
@@ -630,8 +638,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
}
}
}
- png_free(png_ptr, png_ptr->quantize_sort);
- png_ptr->quantize_sort = NULL;
+ png_free(png_ptr, quantize_sort);
}
else
{
@@ -1774,19 +1781,51 @@ png_init_read_transformations(png_structrp png_ptr)
}
else /* if (png_ptr->trans_alpha[i] != 0xff) */
{
- png_byte v, w;
-
- v = png_ptr->gamma_to_1[palette[i].red];
- png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);
- palette[i].red = png_ptr->gamma_from_1[w];
-
- v = png_ptr->gamma_to_1[palette[i].green];
- png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);
- palette[i].green = png_ptr->gamma_from_1[w];
-
- v = png_ptr->gamma_to_1[palette[i].blue];
- png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
- palette[i].blue = png_ptr->gamma_from_1[w];
+ if ((png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0)
+ {
+ /* Premultiply only:
+ * component = round((component * alpha) / 255)
+ */
+ png_uint_32 component;
+
+ component = png_ptr->gamma_to_1[palette[i].red];
+ component =
+ (component * png_ptr->trans_alpha[i] + 128) / 255;
+ palette[i].red = png_ptr->gamma_from_1[component];
+
+ component = png_ptr->gamma_to_1[palette[i].green];
+ component =
+ (component * png_ptr->trans_alpha[i] + 128) / 255;
+ palette[i].green = png_ptr->gamma_from_1[component];
+
+ component = png_ptr->gamma_to_1[palette[i].blue];
+ component =
+ (component * png_ptr->trans_alpha[i] + 128) / 255;
+ palette[i].blue = png_ptr->gamma_from_1[component];
+ }
+ else
+ {
+ /* Composite with background color:
+ * component =
+ * alpha * component + (1 - alpha) * background
+ */
+ png_byte v, w;
+
+ v = png_ptr->gamma_to_1[palette[i].red];
+ png_composite(w, v,
+ png_ptr->trans_alpha[i], back_1.red);
+ palette[i].red = png_ptr->gamma_from_1[w];
+
+ v = png_ptr->gamma_to_1[palette[i].green];
+ png_composite(w, v,
+ png_ptr->trans_alpha[i], back_1.green);
+ palette[i].green = png_ptr->gamma_from_1[w];
+
+ v = png_ptr->gamma_to_1[palette[i].blue];
+ png_composite(w, v,
+ png_ptr->trans_alpha[i], back_1.blue);
+ palette[i].blue = png_ptr->gamma_from_1[w];
+ }
}
}
else
@@ -5009,13 +5048,8 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
#ifdef PNG_READ_QUANTIZE_SUPPORTED
if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
- {
png_do_quantize(row_info, png_ptr->row_buf + 1,
png_ptr->palette_lookup, png_ptr->quantize_index);
-
- if (row_info->rowbytes == 0)
- png_error(png_ptr, "png_do_quantize returned rowbytes=0");
- }
#endif /* READ_QUANTIZE */
#ifdef PNG_READ_EXPAND_16_SUPPORTED
diff --git a/src/3rdparty/libpng/pngstruct.h b/src/3rdparty/libpng/pngstruct.h
index 084422bc1e2..fe5fa041554 100644
--- a/src/3rdparty/libpng/pngstruct.h
+++ b/src/3rdparty/libpng/pngstruct.h
@@ -405,7 +405,6 @@ struct png_struct_def
#ifdef PNG_READ_QUANTIZE_SUPPORTED
/* The following three members were added at version 1.0.14 and 1.2.4 */
- png_bytep quantize_sort; /* working sort array */
png_bytep index_to_palette; /* where the original index currently is
in the palette */
png_bytep palette_to_index; /* which original index points to this
diff --git a/src/3rdparty/libpng/pngwrite.c b/src/3rdparty/libpng/pngwrite.c
index 35a5d17b601..83148960eff 100644
--- a/src/3rdparty/libpng/pngwrite.c
+++ b/src/3rdparty/libpng/pngwrite.c
@@ -2173,8 +2173,7 @@ png_image_write_main(png_voidp argument)
* before it is written. This only applies when the input is 16-bit and
* either there is an alpha channel or it is converted to 8-bit.
*/
- if ((linear != 0 && alpha != 0 ) ||
- (colormap == 0 && display->convert_to_8bit != 0))
+ if (linear != 0 && (alpha != 0 || display->convert_to_8bit != 0))
{
png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr,
png_get_rowbytes(png_ptr, info_ptr)));
diff --git a/src/3rdparty/libpng/qt_attribution.json b/src/3rdparty/libpng/qt_attribution.json
index 9327dee564c..fe8ba663881 100644
--- a/src/3rdparty/libpng/qt_attribution.json
+++ b/src/3rdparty/libpng/qt_attribution.json
@@ -7,8 +7,8 @@
"Description": "libpng is the official PNG reference library.",
"Homepage": "http://www.libpng.org/pub/png/libpng.html",
- "Version": "1.6.50",
- "DownloadLocation": "https://download.sourceforge.net/libpng/libpng-1.6.50.tar.xz",
+ "Version": "1.6.51",
+ "DownloadLocation": "https://download.sourceforge.net/libpng/libpng-1.6.51.tar.xz",
"PURL": "pkg:github/pnggroup/libpng@v$<VERSION>",
"CPE": "cpe:2.3:a:libpng:libpng:$<VERSION>:*:*:*:*:*:*:*",
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index 55d375f0350..f31968f8199 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -1510,6 +1510,7 @@ endif()
qt_internal_extend_target(Core CONDITION WASM
SOURCES
+ platform/wasm/qwasmanimationdriver.cpp platform/wasm/qwasmanimationdriver_p.h
platform/wasm/qwasmglobal.cpp platform/wasm/qwasmglobal_p.h
platform/wasm/qstdweb.cpp platform/wasm/qstdweb_p.h
platform/wasm/qwasmsocket.cpp platform/wasm/qwasmsocket_p.h
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp
index 17814c6756a..c3e1ba4010f 100644
--- a/src/corelib/animation/qabstractanimation.cpp
+++ b/src/corelib/animation/qabstractanimation.cpp
@@ -113,6 +113,10 @@
#include "qabstractanimation_p.h"
+#if defined(Q_OS_WASM)
+#include <QtCore/private/qwasmanimationdriver_p.h>
+#endif
+
#include <QtCore/qmath.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qpointer.h>
diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h
index b4f462071a7..1eaa475f613 100644
--- a/src/corelib/animation/qabstractanimation_p.h
+++ b/src/corelib/animation/qabstractanimation_p.h
@@ -23,6 +23,10 @@
#include <private/qproperty_p.h>
#include <qabstractanimation.h>
+#if defined(Q_OS_WASM)
+#include <QtCore/private/qwasmanimationdriver_p.h>
+#endif
+
QT_REQUIRE_CONFIG(animation);
QT_BEGIN_NAMESPACE
@@ -184,7 +188,11 @@ private:
friend class QAnimationDriver;
QAnimationDriver *driver;
+#if defined(Q_OS_WASM)
+ QWasmAnimationDriver defaultDriver;
+#else
QDefaultAnimationDriver defaultDriver;
+#endif
QBasicTimer pauseTimer;
diff --git a/src/corelib/platform/wasm/qwasmanimationdriver.cpp b/src/corelib/platform/wasm/qwasmanimationdriver.cpp
new file mode 100644
index 00000000000..ab0c8240dd1
--- /dev/null
+++ b/src/corelib/platform/wasm/qwasmanimationdriver.cpp
@@ -0,0 +1,129 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwasmanimationdriver_p.h"
+#include "qwasmsuspendresumecontrol_p.h"
+
+#include <emscripten/val.h>
+
+QT_BEGIN_NAMESPACE
+
+
+// QWasmAnimationDriver drives animations using requestAnimationFrame(). This
+// ensures that animations are advanced in sync with frame update calls, which
+// again are synced to the screen refresh rate.
+
+namespace {
+ constexpr int FallbackTimerInterval = 500;
+}
+
+QWasmAnimationDriver::QWasmAnimationDriver(QUnifiedTimer *)
+ : QAnimationDriver(nullptr)
+{
+ connect(this, &QAnimationDriver::started, this, &QWasmAnimationDriver::start);
+ connect(this, &QAnimationDriver::stopped, this, &QWasmAnimationDriver::stop);
+}
+
+QWasmAnimationDriver::~QWasmAnimationDriver()
+{
+ disconnect(this, &QAnimationDriver::started, this, &QWasmAnimationDriver::start);
+ disconnect(this, &QAnimationDriver::stopped, this, &QWasmAnimationDriver::stop);
+
+ if (m_animateCallbackHandle != 0)
+ QWasmAnimationFrameMultiHandler::instance()->unregisterAnimateCallback(m_animateCallbackHandle);
+}
+
+qint64 QWasmAnimationDriver::elapsed() const
+{
+ return isRunning() ? qint64(m_currentTimestamp - m_startTimestamp) : 0;
+}
+
+double QWasmAnimationDriver::getCurrentTimeFromTimeline() const
+{
+ // Get the current timeline time, which is an equivalent time source to the
+ // animation frame time source. According to the documentation this API
+ // may be unavailable in various cases; check for null before accessing.
+ emscripten::val document = emscripten::val::global("document");
+ emscripten::val timeline = document["timeline"];
+ if (!timeline.isNull() && !timeline.isUndefined()) {
+ emscripten::val currentTime = timeline["currentTime"];
+ if (!currentTime.isNull() && !currentTime.isUndefined())
+ return currentTime.as<double>();
+ }
+ return 0;
+}
+
+void QWasmAnimationDriver::handleFallbackTimeout()
+{
+ if (!isRunning())
+ return;
+
+ // Get the current time from a timing source equivalent to the animation frame time
+ double currentTime = getCurrentTimeFromTimeline();
+ if (currentTime == 0)
+ currentTime = m_currentTimestamp + FallbackTimerInterval;
+ const double timeSinceLastFrame = currentTime - m_currentTimestamp;
+
+ // Advance animations if animations are active but there has been no rcent animation
+ // frame callback.
+ if (timeSinceLastFrame > FallbackTimerInterval * 0.8) {
+ m_currentTimestamp = currentTime;
+ advance();
+ }
+}
+
+void QWasmAnimationDriver::start()
+{
+ if (isRunning())
+ return;
+
+ // Set start timestamp to document.timeline.currentTime()
+ m_startTimestamp = getCurrentTimeFromTimeline();
+ m_currentTimestamp = m_startTimestamp;
+
+ // Register animate callback
+ m_animateCallbackHandle = QWasmAnimationFrameMultiHandler::instance()->registerAnimateCallback(
+ [this](double timestamp) { handleAnimationFrame(timestamp); });
+
+ // Start fallback timer to ensure animations advance even if animaton frame callbacks stop coming
+ fallbackTimer.setInterval(FallbackTimerInterval);
+ connect(&fallbackTimer, &QTimer::timeout, this, &QWasmAnimationDriver::handleFallbackTimeout);
+ fallbackTimer.start();
+
+ QAnimationDriver::start();
+}
+
+void QWasmAnimationDriver::stop()
+{
+ m_startTimestamp = 0;
+ m_currentTimestamp = 0;
+
+ // Stop and disconnect the fallback timer
+ fallbackTimer.stop();
+ disconnect(&fallbackTimer, &QTimer::timeout, this, &QWasmAnimationDriver::handleFallbackTimeout);
+
+ // Deregister the animation frame callback
+ if (m_animateCallbackHandle != 0) {
+ QWasmAnimationFrameMultiHandler::instance()->unregisterAnimateCallback(m_animateCallbackHandle);
+ m_animateCallbackHandle = 0;
+ }
+
+ QAnimationDriver::stop();
+}
+
+void QWasmAnimationDriver::handleAnimationFrame(double timestamp)
+{
+ if (!isRunning())
+ return;
+
+ m_currentTimestamp = timestamp;
+
+ // Fall back to setting m_startTimestamp here in cases where currentTime
+ // was not available in start() (gives 0 elapsed time for the first frame)
+ if (m_startTimestamp == 0)
+ m_startTimestamp = timestamp;
+
+ advance();
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/platform/wasm/qwasmanimationdriver_p.h b/src/corelib/platform/wasm/qwasmanimationdriver_p.h
new file mode 100644
index 00000000000..f8435c17a9a
--- /dev/null
+++ b/src/corelib/platform/wasm/qwasmanimationdriver_p.h
@@ -0,0 +1,54 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWASMANIMATIONDRIVER_P_H
+#define QWASMANIMATIONDRIVER_P_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 <QtCore/private/qglobal_p.h>
+#include <QtCore/qabstractanimation.h>
+#include <QtCore/qtimer.h>
+
+#include <memory>
+
+QT_BEGIN_NAMESPACE
+
+class QUnifiedTimer;
+
+class Q_CORE_EXPORT QWasmAnimationDriver : public QAnimationDriver
+{
+ Q_OBJECT
+public:
+ QWasmAnimationDriver(QUnifiedTimer *unifiedTimer);
+ ~QWasmAnimationDriver() override;
+
+ qint64 elapsed() const override;
+
+protected:
+ void start() override;
+ void stop() override;
+
+private:
+ void handleAnimationFrame(double timestamp);
+ void handleFallbackTimeout();
+ double getCurrentTimeFromTimeline() const;
+
+ QTimer fallbackTimer;
+ uint32_t m_animateCallbackHandle = 0;
+ double m_startTimestamp = 0;
+ double m_currentTimestamp = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWASMANIMATIONDRIVER_P_H
diff --git a/src/corelib/platform/wasm/qwasmsuspendresumecontrol.cpp b/src/corelib/platform/wasm/qwasmsuspendresumecontrol.cpp
index 093898c520a..5fe92926240 100644
--- a/src/corelib/platform/wasm/qwasmsuspendresumecontrol.cpp
+++ b/src/corelib/platform/wasm/qwasmsuspendresumecontrol.cpp
@@ -4,6 +4,8 @@
#include "qwasmsuspendresumecontrol_p.h"
#include "qstdweb_p.h"
+#include <QtCore/qapplicationstatic.h>
+
#include <emscripten.h>
#include <emscripten/val.h>
#include <emscripten/bind.h>
@@ -75,32 +77,20 @@ void qtRegisterEventHandlerJs(int index) {
}[name];
}
- function deepShallowClone(parent, obj, depth) {
+ function deepShallowClone(obj) {
if (obj === null)
return obj;
- if (typeof obj === 'function') {
- if (obj.name !== "")
- return createNamedFunction(obj.name, parent, obj);
- }
-
- if (depth >= 1)
- return obj;
-
- if (typeof obj !== 'object')
+ if (!(obj instanceof Event))
return obj;
- if (Array.isArray(obj)) {
- const arrCopy = [];
- for (let i = 0; i < obj.length; i++)
- arrCopy[i] = deepShallowClone(obj, obj[i], depth + 1);
-
- return arrCopy;
- }
-
const objCopy = {};
- for (const key in obj)
- objCopy[key] = deepShallowClone(obj, obj[key], depth + 1);
+ for (const key in obj) {
+ if (typeof obj[key] === 'function')
+ objCopy[key] = createNamedFunction(obj[key].name, obj, obj[key]);
+ else
+ objCopy[key] = obj[key];
+ }
return objCopy;
}
@@ -110,7 +100,7 @@ void qtRegisterEventHandlerJs(int index) {
let handler = (arg) => {
// Copy the top level object, alias the rest.
// functions are copied by creating new forwarding functions.
- arg = deepShallowClone(arg, arg, 0);
+ arg = deepShallowClone(arg);
// Add event to event queue
control.pendingEvents.push({
@@ -357,3 +347,103 @@ void QWasmTimer::clearTimeout()
val::global("window").call<void>("clearTimeout", double(m_timerId));
m_timerId = 0;
}
+
+//
+// QWasmAnimationFrameMultiHandler
+//
+// Multiplexes multiple animate and draw callbacks to a single native requestAnimationFrame call.
+// Animate callbacks are called before draw callbacks to ensure animations are advanced before drawing.
+//
+QWasmAnimationFrameMultiHandler::QWasmAnimationFrameMultiHandler()
+{
+ auto wrapper = [this](val arg) {
+ handleAnimationFrame(arg.as<double>());
+ };
+ m_handlerIndex = QWasmSuspendResumeControl::get()->registerEventHandler(wrapper);
+}
+
+QWasmAnimationFrameMultiHandler::~QWasmAnimationFrameMultiHandler()
+{
+ cancelAnimationFrameRequest();
+ QWasmSuspendResumeControl::get()->removeEventHandler(m_handlerIndex);
+}
+
+Q_APPLICATION_STATIC(QWasmAnimationFrameMultiHandler, s_animationFrameHandler);
+QWasmAnimationFrameMultiHandler *QWasmAnimationFrameMultiHandler::instance()
+{
+ return s_animationFrameHandler();
+}
+
+// Registers a permanent animation callback. Call unregisterAnimateCallback() to unregister
+uint32_t QWasmAnimationFrameMultiHandler::registerAnimateCallback(Callback callback)
+{
+ uint32_t handle = ++m_nextAnimateHandle;
+ m_animateCallbacks[handle] = std::move(callback);
+ ensureAnimationFrameRequested();
+ return handle;
+}
+
+// Registers a single-shot draw callback.
+uint32_t QWasmAnimationFrameMultiHandler::registerDrawCallback(Callback callback)
+{
+ uint32_t handle = ++m_nextDrawHandle;
+ m_drawCallbacks[handle] = std::move(callback);
+ ensureAnimationFrameRequested();
+ return handle;
+}
+
+void QWasmAnimationFrameMultiHandler::unregisterAnimateCallback(uint32_t handle)
+{
+ m_animateCallbacks.erase(handle);
+ if (m_animateCallbacks.empty() && m_drawCallbacks.empty())
+ cancelAnimationFrameRequest();
+}
+
+void QWasmAnimationFrameMultiHandler::unregisterDrawCallback(uint32_t handle)
+{
+ m_drawCallbacks.erase(handle);
+ if (m_animateCallbacks.empty() && m_drawCallbacks.empty())
+ cancelAnimationFrameRequest();
+}
+
+void QWasmAnimationFrameMultiHandler::handleAnimationFrame(double timestamp)
+{
+ m_requestId = -1;
+
+ // Advance animations. Copy the callbacks list in case callbacks are
+ // unregistered during iteration
+ auto animateCallbacksCopy = m_animateCallbacks;
+ for (const auto &pair : animateCallbacksCopy)
+ pair.second(timestamp);
+
+ // Draw the frame. Note that draw callbacks are cleared after each
+ // frame, matching QWindow::requestUpdate() behavior. Copy the callbacks
+ // list in case new callbacks are registered while drawing the frame
+ auto drawCallbacksCopy = m_drawCallbacks;
+ m_drawCallbacks.clear();
+ for (const auto &pair : drawCallbacksCopy)
+ pair.second(timestamp);
+
+ // Request next frame if there are still callbacks registered
+ if (!m_animateCallbacks.empty() || !m_drawCallbacks.empty())
+ ensureAnimationFrameRequested();
+}
+
+void QWasmAnimationFrameMultiHandler::ensureAnimationFrameRequested()
+{
+ if (m_requestId != -1)
+ return;
+
+ using ReturnType = double;
+ val handler = QWasmSuspendResumeControl::get()->jsEventHandlerAt(m_handlerIndex);
+ m_requestId = int64_t(val::global("window").call<ReturnType>("requestAnimationFrame", handler));
+}
+
+void QWasmAnimationFrameMultiHandler::cancelAnimationFrameRequest()
+{
+ if (m_requestId == -1)
+ return;
+
+ val::global("window").call<void>("cancelAnimationFrame", double(m_requestId));
+ m_requestId = -1;
+}
diff --git a/src/corelib/platform/wasm/qwasmsuspendresumecontrol_p.h b/src/corelib/platform/wasm/qwasmsuspendresumecontrol_p.h
index 37c71ed8123..b750d80314c 100644
--- a/src/corelib/platform/wasm/qwasmsuspendresumecontrol_p.h
+++ b/src/corelib/platform/wasm/qwasmsuspendresumecontrol_p.h
@@ -83,4 +83,37 @@ private:
uint64_t m_timerId = 0;
};
+class Q_CORE_EXPORT QWasmAnimationFrameMultiHandler
+{
+public:
+ using Callback = std::function<void(double)>;
+
+ static QWasmAnimationFrameMultiHandler *instance();
+
+ uint32_t registerAnimateCallback(Callback callback);
+ uint32_t registerDrawCallback(Callback callback);
+
+ void unregisterAnimateCallback(uint32_t handle);
+ void unregisterDrawCallback(uint32_t handle);
+
+ QWasmAnimationFrameMultiHandler();
+ ~QWasmAnimationFrameMultiHandler();
+ QWasmAnimationFrameMultiHandler(const QWasmAnimationFrameMultiHandler&) = delete;
+ QWasmAnimationFrameMultiHandler& operator=(const QWasmAnimationFrameMultiHandler&) = delete;
+
+private:
+ void handleAnimationFrame(double timestamp);
+ void ensureAnimationFrameRequested();
+ void cancelAnimationFrameRequest();
+
+ static QWasmAnimationFrameMultiHandler *s_instance;
+
+ std::map<uint32_t, Callback> m_animateCallbacks;
+ std::map<uint32_t, Callback> m_drawCallbacks;
+ uint32_t m_nextAnimateHandle = 0;
+ uint32_t m_nextDrawHandle = 0;
+ uint32_t m_handlerIndex = 0;
+ int64_t m_requestId = -1;
+};
+
#endif
diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp
index 092ff46b084..53cca38ba7b 100644
--- a/src/corelib/tools/qcryptographichash.cpp
+++ b/src/corelib/tools/qcryptographichash.cpp
@@ -101,8 +101,6 @@ static inline int SHA384_512AddLength(SHA512Context *context, unsigned int lengt
}
#endif // !QT_CONFIG(opensslv30)
-#include "qtcore-config_p.h"
-
#if QT_CONFIG(system_libb2)
#include <blake2.h>
#else
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 6fe1ce38a61..9f59d11375b 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -5,7 +5,6 @@
#include "qhttpnetworkconnectionchannel_p.h"
#include "qhttpnetworkconnection_p.h"
-#include "qhttp2configuration.h"
#include "private/qnoncontiguousbytedevice_p.h"
#include <qdebug.h>
@@ -34,6 +33,12 @@ QT_BEGIN_NAMESPACE
// connection times out)
// We use 3 because we can get a _q_error 3 times depending on the timing:
static const int reconnectAttemptsDefault = 3;
+static const char keepAliveIdleOption[] = "QT_QNAM_TCP_KEEPIDLE";
+static const char keepAliveIntervalOption[] = "QT_QNAM_TCP_KEEPINTVL";
+static const char keepAliveCountOption[] = "QT_QNAM_TCP_KEEPCNT";
+static const int TCP_KEEPIDLE_DEF = 60;
+static const int TCP_KEEPINTVL_DEF = 10;
+static const int TCP_KEEPCNT_DEF = 5;
QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel()
: socket(nullptr)
@@ -914,6 +919,13 @@ void QHttpNetworkConnectionChannel::_q_connected_abstract_socket(QAbstractSocket
// not sure yet if it helps, but it makes sense
absSocket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
+ int kaIdleOption = qEnvironmentVariableIntegerValue(keepAliveIdleOption).value_or(TCP_KEEPIDLE_DEF);
+ int kaIntervalOption = qEnvironmentVariableIntegerValue(keepAliveIntervalOption).value_or(TCP_KEEPINTVL_DEF);
+ int kaCountOption = qEnvironmentVariableIntegerValue(keepAliveCountOption).value_or(TCP_KEEPCNT_DEF);
+ absSocket->setSocketOption(QAbstractSocket::KeepAliveIdleOption, kaIdleOption);
+ absSocket->setSocketOption(QAbstractSocket::KeepAliveIntervalOption, kaIntervalOption);
+ absSocket->setSocketOption(QAbstractSocket::KeepAliveCountOption, kaCountOption);
+
pipeliningSupported = QHttpNetworkConnectionChannel::PipeliningSupportUnknown;
// ### FIXME: if the server closes the connection unexpectedly, we shouldn't send the same broken request again!
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index 3c9cae1fe8b..975332a14ab 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -360,6 +360,21 @@
allow setting the MTU for transmission.
This enum value was introduced in Qt 5.11.
+ \value KeepAliveIdleOption The time in seconds the connection needs to
+ remain idle before TCP starts sending keepalive probes if
+ KeepAliveOption is enabled.
+ This enum value was introduced in Qt 6.11.
+
+ \value KeepAliveIntervalOption The time in seconds between individual
+ keepalive probes, if KeepAliveOption is enabled. This option is not
+ supported in all OSes.
+ This enum value was introduced in Qt 6.11.
+
+ \value KeepAliveCountOption The maximum number of keepalive probes to
+ send before TCP drops the connection, if KeepAliveOption is enabled.
+ This option is not supported in all OSes.
+ This enum value was introduced in Qt 6.11.
+
Possible values for \e{TypeOfServiceOption} are:
\table
@@ -1973,6 +1988,18 @@ void QAbstractSocket::setSocketOption(QAbstractSocket::SocketOption option, cons
case PathMtuSocketOption:
d_func()->socketEngine->setOption(QAbstractSocketEngine::PathMtuInformation, value.toInt());
break;
+
+ case KeepAliveIdleOption:
+ d_func()->socketEngine->setOption(QAbstractSocketEngine::KeepAliveIdleOption, value.toInt());
+ break;
+
+ case KeepAliveIntervalOption:
+ d_func()->socketEngine->setOption(QAbstractSocketEngine::KeepAliveIntervalOption, value.toInt());
+ break;
+
+ case KeepAliveCountOption:
+ d_func()->socketEngine->setOption(QAbstractSocketEngine::KeepAliveCountOption, value.toInt());
+ break;
}
}
@@ -2019,6 +2046,18 @@ QVariant QAbstractSocket::socketOption(QAbstractSocket::SocketOption option)
case PathMtuSocketOption:
ret = d_func()->socketEngine->option(QAbstractSocketEngine::PathMtuInformation);
break;
+
+ case KeepAliveIdleOption:
+ ret = d_func()->socketEngine->option(QAbstractSocketEngine::KeepAliveIdleOption);
+ break;
+
+ case KeepAliveIntervalOption:
+ ret = d_func()->socketEngine->option(QAbstractSocketEngine::KeepAliveIntervalOption);
+ break;
+
+ case KeepAliveCountOption:
+ ret = d_func()->socketEngine->option(QAbstractSocketEngine::KeepAliveCountOption);
+ break;
}
if (ret == -1)
return QVariant();
diff --git a/src/network/socket/qabstractsocket.h b/src/network/socket/qabstractsocket.h
index 8d2e8a299cc..e0707a8ca8a 100644
--- a/src/network/socket/qabstractsocket.h
+++ b/src/network/socket/qabstractsocket.h
@@ -108,7 +108,10 @@ public:
TypeOfServiceOption, //IP_TOS
SendBufferSizeSocketOption, //SO_SNDBUF
ReceiveBufferSizeSocketOption, //SO_RCVBUF
- PathMtuSocketOption // IP_MTU
+ PathMtuSocketOption, // IP_MTU
+ KeepAliveIdleOption, // TCP_KEEPIDLE
+ KeepAliveIntervalOption, // TCP_KEEPINTVL
+ KeepAliveCountOption // TCP_KEEPCNT
};
Q_ENUM(SocketOption)
enum BindFlag {
diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h
index 9340df009a7..c1d9ca56a7f 100644
--- a/src/network/socket/qabstractsocketengine_p.h
+++ b/src/network/socket/qabstractsocketengine_p.h
@@ -65,6 +65,9 @@ public:
MaxStreamsSocketOption,
PathMtuInformation,
BindInterfaceIndex,
+ KeepAliveIdleOption,
+ KeepAliveIntervalOption,
+ KeepAliveCountOption,
};
enum PacketHeaderOption {
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index 430197ccc6e..e920de11c13 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -170,6 +170,26 @@ static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt,
#endif
}
break;
+ case QNativeSocketEngine::KeepAliveIdleOption:
+ level = IPPROTO_TCP;
+#ifdef TCP_KEEPALIVE
+ n = TCP_KEEPALIVE;
+#else
+ n = TCP_KEEPIDLE;
+#endif
+ break;
+ case QNativeSocketEngine::KeepAliveIntervalOption:
+#ifdef TCP_KEEPINTVL
+ level = IPPROTO_TCP;
+ n = TCP_KEEPINTVL;
+#endif
+ break;
+ case QNativeSocketEngine::KeepAliveCountOption:
+#ifdef TCP_KEEPCNT
+ level = IPPROTO_TCP;
+ n = TCP_KEEPCNT;
+#endif
+ break;
}
}
@@ -200,7 +220,7 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
int socket = qt_safe_socket(domain, type, protocol, O_NONBLOCK);
- if (socket < 0 && socketProtocol == QAbstractSocket::AnyIPProtocol && errno == EAFNOSUPPORT) {
+ if (socket < 0 && socketProtocol == QAbstractSocket::AnyIPProtocol && (errno == EAFNOSUPPORT || errno == ENOTSUP )) {
domain = AF_INET;
socket = qt_safe_socket(domain, type, protocol, O_NONBLOCK);
socketProtocol = QAbstractSocket::IPv4Protocol;
@@ -1161,6 +1181,8 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
sentBytes = -2;
break;
case EMSGSIZE:
+ // seen on VxWorks
+ case ENOMEM:
setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
break;
case ECONNRESET:
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index 598467ef629..8530c6ca819 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
+++ b/src/network/socket/qnativesocketengine_win.cpp
@@ -34,6 +34,15 @@ QT_BEGIN_NAMESPACE
#ifndef IP_HOPLIMIT
#define IP_HOPLIMIT 21 // Receive packet hop limit.
#endif
+#ifndef TCP_KEEPIDLE
+#define TCP_KEEPIDLE 3
+#endif
+#ifndef TCP_KEEPINTVL
+#define TCP_KEEPINTVL 17
+#endif
+#ifndef TCP_KEEPCNT
+#define TCP_KEEPCNT 16
+#endif
#if defined(QNATIVESOCKETENGINE_DEBUG)
@@ -216,6 +225,18 @@ static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt,
case QAbstractSocketEngine::PathMtuInformation:
break; // not supported on Windows
+ case QNativeSocketEngine::KeepAliveIdleOption:
+ level = IPPROTO_TCP;
+ n = TCP_KEEPIDLE; // defined in ws2ipdef.h
+ break;
+ case QNativeSocketEngine::KeepAliveIntervalOption:
+ level = IPPROTO_TCP;
+ n = TCP_KEEPINTVL; // defined in ws2ipdef.h
+ break;
+ case QNativeSocketEngine::KeepAliveCountOption:
+ level = IPPROTO_TCP;
+ n = TCP_KEEPCNT; // defined in ws2ipdef.h
+ break;
}
}
diff --git a/src/plugins/platforms/cocoa/qnsview_mouse.mm b/src/plugins/platforms/cocoa/qnsview_mouse.mm
index 56ff5ec313e..ca7e9c808f7 100644
--- a/src/plugins/platforms/cocoa/qnsview_mouse.mm
+++ b/src/plugins/platforms/cocoa/qnsview_mouse.mm
@@ -290,8 +290,7 @@ static const QPointingDevice *pointingDeviceFor(qint64 deviceID)
if (qIsNaN(windowPoint.x) || qIsNaN(windowPoint.y)) {
screenPoint = [NSEvent mouseLocation];
} else {
- NSRect screenRect = [[theEvent window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)];
- screenPoint = screenRect.origin;
+ screenPoint = [theEvent.window convertPointToScreen:windowPoint];
}
} else {
screenPoint = [NSEvent mouseLocation];
diff --git a/src/plugins/platforms/direct2d/CMakeLists.txt b/src/plugins/platforms/direct2d/CMakeLists.txt
index 0b3ecf33967..38d7e4160a5 100644
--- a/src/plugins/platforms/direct2d/CMakeLists.txt
+++ b/src/plugins/platforms/direct2d/CMakeLists.txt
@@ -33,6 +33,7 @@ qt_internal_add_plugin(QWindowsDirect2DIntegrationPlugin
../windows/qwindowstheme.cpp ../windows/qwindowstheme.h
../windows/qwindowsthreadpoolrunner.h
../windows/qwindowswindow.cpp ../windows/qwindowswindow.h
+ ../windows/qwindowswindowclassdescription.cpp ../windows/qwindowswindowclassdescription.h
../windows/qwindowswindowclassregistry.cpp ../windows/qwindowswindowclassregistry.h
qwindowsdirect2dbackingstore.cpp qwindowsdirect2dbackingstore.h
qwindowsdirect2dbitmap.cpp qwindowsdirect2dbitmap.h
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp
index 99cf8885af5..1b43ff78991 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.cpp
+++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp
@@ -17,19 +17,14 @@ bool QWasmCompositor::m_requestUpdateHoldEnabled = false;
QWasmCompositor::QWasmCompositor(QWasmScreen *screen)
: QObject(screen)
-, m_animationFrameHandler(QWasmAnimationFrameHandler([this](double frametime){
- Q_UNUSED(frametime);
- this->m_requestAnimationFrameId = -1;
- this->deliverUpdateRequests();
- }))
{
QWindowSystemInterface::setSynchronousWindowSystemEvents(true);
}
QWasmCompositor::~QWasmCompositor()
{
- if (m_requestAnimationFrameId != -1)
- m_animationFrameHandler.cancelAnimationFrame(m_requestAnimationFrameId);
+ if (m_drawCallbackHandle != 0)
+ QWasmAnimationFrameMultiHandler::instance()->unregisterDrawCallback(m_drawCallbackHandle);
// TODO(mikolaj.boc): Investigate if m_isEnabled is needed at all. It seems like a frame should
// not be generated after this instead.
@@ -87,13 +82,18 @@ void QWasmCompositor::requestUpdateWindow(QWasmWindow *window, const QRect &upda
// Requests an update/new frame using RequestAnimationFrame
void QWasmCompositor::requestUpdate()
{
- if (m_requestAnimationFrameId != -1)
+ if (m_drawCallbackHandle != 0)
return;
if (m_requestUpdateHoldEnabled)
return;
- m_requestAnimationFrameId = m_animationFrameHandler.requestAnimationFrame();
+ m_drawCallbackHandle = QWasmAnimationFrameMultiHandler::instance()->registerDrawCallback(
+ [this](double frametime) {
+ Q_UNUSED(frametime);
+ m_drawCallbackHandle = 0;
+ deliverUpdateRequests();
+ });
}
void QWasmCompositor::deliverUpdateRequests()
@@ -165,28 +165,3 @@ QWasmScreen *QWasmCompositor::screen()
{
return static_cast<QWasmScreen *>(parent());
}
-
-QWasmAnimationFrameHandler::QWasmAnimationFrameHandler(std::function<void(double)> handler)
-{
- auto argCastWrapper = [handler](val arg){ handler(arg.as<double>()); };
- m_handlerIndex = QWasmSuspendResumeControl::get()->registerEventHandler(argCastWrapper);
-}
-
-QWasmAnimationFrameHandler::~QWasmAnimationFrameHandler()
-{
- QWasmSuspendResumeControl::get()->removeEventHandler(m_handlerIndex);
-}
-
-int64_t QWasmAnimationFrameHandler::requestAnimationFrame()
-{
- using ReturnType = double; // FIXME emscripten::val::call() does not support int64_t
- val handler = QWasmSuspendResumeControl::get()->jsEventHandlerAt(m_handlerIndex);
- return int64_t(val::global("window").call<ReturnType>("requestAnimationFrame", handler));
-}
-
-void QWasmAnimationFrameHandler::cancelAnimationFrame(int64_t id)
-{
- val::global("window").call<void>("cancelAnimationFrame", double(id));
-}
-
-
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h
index 8fc290dda3b..eb529a3d30b 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.h
+++ b/src/plugins/platforms/wasm/qwasmcompositor.h
@@ -7,6 +7,7 @@
#include "qwasmwindowstack.h"
#include <qpa/qplatformwindow.h>
+#include <private/qwasmsuspendresumecontrol_p.h>
#include <QMap>
#include <tuple>
@@ -20,18 +21,6 @@ class QWasmScreen;
enum class QWasmWindowTreeNodeChangeType;
-class QWasmAnimationFrameHandler
-{
-public:
- QWasmAnimationFrameHandler(std::function<void(double)> handler);
- ~QWasmAnimationFrameHandler();
- int64_t requestAnimationFrame();
- void cancelAnimationFrame(int64_t id);
-
-private:
- uint32_t m_handlerIndex;
-};
-
class QWasmCompositor final : public QObject
{
Q_OBJECT
@@ -65,8 +54,7 @@ private:
bool m_isEnabled = true;
QMap<QWasmWindow *, std::tuple<QRect, UpdateRequestDeliveryType>> m_requestUpdateWindows;
- QWasmAnimationFrameHandler m_animationFrameHandler;
- int64_t m_requestAnimationFrameId = -1;
+ uint32_t m_drawCallbackHandle = 0;
bool m_inDeliverUpdateRequest = false;
static bool m_requestUpdateHoldEnabled;
};
diff --git a/src/plugins/platforms/windows/CMakeLists.txt b/src/plugins/platforms/windows/CMakeLists.txt
index c7563c72979..40f173c8c82 100644
--- a/src/plugins/platforms/windows/CMakeLists.txt
+++ b/src/plugins/platforms/windows/CMakeLists.txt
@@ -38,6 +38,7 @@ qt_internal_add_plugin(QWindowsIntegrationPlugin
qwindowstheme.cpp qwindowstheme.h
qwindowsthreadpoolrunner.h
qwindowswindow.cpp qwindowswindow.h
+ qwindowswindowclassdescription.cpp qwindowswindowclassdescription.h
qwindowswindowclassregistry.cpp qwindowswindowclassregistry.h
NO_UNITY_BUILD_SOURCES
qwindowspointerhandler.cpp
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 3013de1c068..156351987cb 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -696,7 +696,7 @@ HWND QWindowsContext::createDummyWindow(const QString &classNameIn,
{
if (!wndProc)
wndProc = DefWindowProc;
- QString className = d->m_windowClassRegistry.registerWindowClass(QWindowsWindowClassRegistry::classNamePrefix() + classNameIn, wndProc);
+ QString className = d->m_windowClassRegistry.registerWindowClass(classNameIn, wndProc);
return CreateWindowEx(0, reinterpret_cast<LPCWSTR>(className.utf16()),
windowName, style,
CW_USEDEFAULT, CW_USEDEFAULT,
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 9139ec0c463..2bd2f0c9e3d 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -704,7 +704,7 @@ void QWindowsScreenManager::initialize()
qCDebug(lcQpaScreen) << "Initializing screen manager";
auto className = QWindowsWindowClassRegistry::instance()->registerWindowClass(
- QWindowsWindowClassRegistry::classNamePrefix() + QLatin1String("ScreenChangeObserverWindow"),
+ QLatin1String("ScreenChangeObserverWindow"),
qDisplayChangeObserverWndProc);
// HWND_MESSAGE windows do not get WM_DISPLAYCHANGE, so we need to create
diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
index a2ce1e86a4d..beeab1a089e 100644
--- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
+++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
@@ -119,9 +119,9 @@ static inline HWND createTrayIconMessageWindow()
if (!ctx)
return nullptr;
// Register window class in the platform plugin.
- const QString className =
- ctx->registerWindowClass(QWindowsWindowClassRegistry::classNamePrefix() + "TrayIconMessageWindowClass"_L1,
- qWindowsTrayIconWndProc);
+ const QString className = ctx->registerWindowClass(
+ "TrayIconMessageWindowClass"_L1,
+ qWindowsTrayIconWndProc);
const wchar_t windowName[] = L"QTrayIconMessageWindow";
return CreateWindowEx(0, reinterpret_cast<const wchar_t *>(className.utf16()),
windowName, WS_OVERLAPPED,
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index 33d7c4124ac..d132bbb6130 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -549,7 +549,7 @@ QWindowsTheme::QWindowsTheme()
refreshIconPixmapSizes();
auto className = QWindowsWindowClassRegistry::instance()->registerWindowClass(
- QWindowsWindowClassRegistry::classNamePrefix() + QLatin1String("ThemeChangeObserverWindow"),
+ QLatin1String("ThemeChangeObserverWindow"),
qThemeChangeObserverWndProc);
// HWND_MESSAGE windows do not get the required theme events,
// so we use a real top-level window that we never show.
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index c49ddbb3247..ed391009423 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -23,6 +23,7 @@
#ifdef QT_NO_CURSOR
# include "qwindowscursor.h"
#endif
+#include "qwindowswindowclassdescription.h"
#include "qwindowswindowclassregistry.h"
#include <QtGui/qguiapplication.h>
@@ -886,7 +887,12 @@ QWindowsWindowData
const auto appinst = reinterpret_cast<HINSTANCE>(GetModuleHandle(nullptr));
const QString windowClassName = QWindowsWindowClassRegistry::instance()->registerWindowClass(w);
- const QString windowTitlebarName = QWindowsWindowClassRegistry::instance()->registerWindowClass(QStringLiteral("_q_titlebar"), DefWindowProc, CS_VREDRAW|CS_HREDRAW, nullptr, false);
+
+ QWindowsWindowClassDescription windowTitlebarDescription;
+ windowTitlebarDescription.name = QStringLiteral("_q_titlebar");
+ windowTitlebarDescription.style = CS_VREDRAW | CS_HREDRAW;
+ windowTitlebarDescription.shouldAddPrefix = false;
+ const QString windowTitlebarName = QWindowsWindowClassRegistry::instance()->registerWindowClass(windowTitlebarDescription);
const QScreen *screen{};
const QRect rect = QPlatformWindow::initialGeometry(w, data.geometry,
diff --git a/src/plugins/platforms/windows/qwindowswindowclassdescription.cpp b/src/plugins/platforms/windows/qwindowswindowclassdescription.cpp
new file mode 100644
index 00000000000..63e16260b62
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowswindowclassdescription.cpp
@@ -0,0 +1,78 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwindowswindowclassdescription.h"
+
+#include <QtGui/qwindow.h>
+
+#include "qwindowswindowclassregistry.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+QWindowsWindowClassDescription QWindowsWindowClassDescription::fromName(QString name, WNDPROC procedure)
+{
+ return { std::move(name), procedure };
+}
+
+QWindowsWindowClassDescription QWindowsWindowClassDescription::fromWindow(const QWindow *window, WNDPROC procedure)
+{
+ Q_ASSERT(window);
+
+ QWindowsWindowClassDescription description;
+ description.procedure = procedure;
+
+ const Qt::WindowFlags flags = window->flags();
+ const Qt::WindowFlags type = flags & Qt::WindowType_Mask;
+ // Determine style and icon.
+ description.style = CS_DBLCLKS;
+ description.hasIcon = true;
+ // The following will not set CS_OWNDC for any widget window, even if it contains a
+ // QOpenGLWidget or QQuickWidget later on. That cannot be detected at this stage.
+ if (window->surfaceType() == QSurface::OpenGLSurface || (flags & Qt::MSWindowsOwnDC))
+ description.style |= CS_OWNDC;
+ if (!(flags & Qt::NoDropShadowWindowHint)
+ && (type == Qt::Popup || window->property("_q_windowsDropShadow").toBool())) {
+ description.style |= CS_DROPSHADOW;
+ }
+ switch (type) {
+ case Qt::Tool:
+ case Qt::ToolTip:
+ case Qt::Popup:
+ description.style |= CS_SAVEBITS; // Save/restore background
+ description.hasIcon = false;
+ break;
+ case Qt::Dialog:
+ if (!(flags & Qt::WindowSystemMenuHint))
+ description.hasIcon = false; // QTBUG-2027, dialogs without system menu.
+ break;
+ }
+ // Create a unique name for the flag combination
+ description.name = "QWindow"_L1;
+ switch (type) {
+ case Qt::Tool:
+ description.name += "Tool"_L1;
+ break;
+ case Qt::ToolTip:
+ description.name += "ToolTip"_L1;
+ break;
+ case Qt::Popup:
+ description.name += "Popup"_L1;
+ break;
+ default:
+ break;
+ }
+ if (description.style & CS_DROPSHADOW)
+ description.name += "DropShadow"_L1;
+ if (description.style & CS_SAVEBITS)
+ description.name += "SaveBits"_L1;
+ if (description.style & CS_OWNDC)
+ description.name += "OwnDC"_L1;
+ if (description.hasIcon)
+ description.name += "Icon"_L1;
+
+ return description;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowswindowclassdescription.h b/src/plugins/platforms/windows/qwindowswindowclassdescription.h
new file mode 100644
index 00000000000..9423abf9d2d
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowswindowclassdescription.h
@@ -0,0 +1,30 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWINDOWSWINDOWCLASSDESCRIPTION_H
+#define QWINDOWSWINDOWCLASSDESCRIPTION_H
+
+#include "qtwindowsglobal.h"
+
+#include <QtCore/qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWindow;
+
+struct QWindowsWindowClassDescription
+{
+ static QWindowsWindowClassDescription fromName(QString name, WNDPROC procedure);
+ static QWindowsWindowClassDescription fromWindow(const QWindow *window, WNDPROC procedure);
+
+ QString name;
+ WNDPROC procedure{ DefWindowProc };
+ unsigned int style{ 0 };
+ HBRUSH brush{ nullptr };
+ bool hasIcon{ false };
+ bool shouldAddPrefix{ true };
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSWINDOWCLASSDESCRIPTION_H
diff --git a/src/plugins/platforms/windows/qwindowswindowclassregistry.cpp b/src/plugins/platforms/windows/qwindowswindowclassregistry.cpp
index 0d405dc419a..c330720a09c 100644
--- a/src/plugins/platforms/windows/qwindowswindowclassregistry.cpp
+++ b/src/plugins/platforms/windows/qwindowswindowclassregistry.cpp
@@ -6,9 +6,9 @@
#include <QtCore/qlibraryinfo.h>
#include <QtCore/quuid.h>
-#include <QtGui/qwindow.h>
#include "qwindowscontext.h"
+#include "qwindowswindowclassdescription.h"
QT_BEGIN_NAMESPACE
@@ -55,64 +55,13 @@ QString QWindowsWindowClassRegistry::classNamePrefix()
return result;
}
-QString QWindowsWindowClassRegistry::registerWindowClass(const QWindow *w)
+QString QWindowsWindowClassRegistry::registerWindowClass(const QWindowsWindowClassDescription &description)
{
- Q_ASSERT(w);
- const Qt::WindowFlags flags = w->flags();
- const Qt::WindowFlags type = flags & Qt::WindowType_Mask;
- // Determine style and icon.
- uint style = CS_DBLCLKS;
- bool icon = true;
- // The following will not set CS_OWNDC for any widget window, even if it contains a
- // QOpenGLWidget or QQuickWidget later on. That cannot be detected at this stage.
- if (w->surfaceType() == QSurface::OpenGLSurface || (flags & Qt::MSWindowsOwnDC))
- style |= CS_OWNDC;
- if (!(flags & Qt::NoDropShadowWindowHint)
- && (type == Qt::Popup || w->property("_q_windowsDropShadow").toBool())) {
- style |= CS_DROPSHADOW;
- }
- switch (type) {
- case Qt::Tool:
- case Qt::ToolTip:
- case Qt::Popup:
- style |= CS_SAVEBITS; // Save/restore background
- icon = false;
- break;
- case Qt::Dialog:
- if (!(flags & Qt::WindowSystemMenuHint))
- icon = false; // QTBUG-2027, dialogs without system menu.
- break;
- }
- // Create a unique name for the flag combination
- QString cname = classNamePrefix();
- cname += "QWindow"_L1;
- switch (type) {
- case Qt::Tool:
- cname += "Tool"_L1;
- break;
- case Qt::ToolTip:
- cname += "ToolTip"_L1;
- break;
- case Qt::Popup:
- cname += "Popup"_L1;
- break;
- default:
- break;
- }
- if (style & CS_DROPSHADOW)
- cname += "DropShadow"_L1;
- if (style & CS_SAVEBITS)
- cname += "SaveBits"_L1;
- if (style & CS_OWNDC)
- cname += "OwnDC"_L1;
- if (icon)
- cname += "Icon"_L1;
-
- return registerWindowClass(cname, m_proc, style, nullptr, icon);
-}
+ QString className = description.name;
+
+ if (description.shouldAddPrefix)
+ className = classNamePrefix() + className;
-QString QWindowsWindowClassRegistry::registerWindowClass(QString cname, WNDPROC proc, unsigned style, HBRUSH brush, bool icon)
-{
// since multiple Qt versions can be used in one process
// each one has to have window class names with a unique name
// The first instance gets the unmodified name; if the class
@@ -122,52 +71,63 @@ QString QWindowsWindowClassRegistry::registerWindowClass(QString cname, WNDPROC
// Note: GetClassInfo() returns != 0 when a class exists.
const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
WNDCLASS wcinfo;
- const bool classExists = GetClassInfo(appInstance, reinterpret_cast<LPCWSTR>(cname.utf16()), &wcinfo) != FALSE
- && wcinfo.lpfnWndProc != proc;
+ const bool classExists = GetClassInfo(appInstance, reinterpret_cast<LPCWSTR>(className.utf16()), &wcinfo) != FALSE
+ && wcinfo.lpfnWndProc != description.procedure;
if (classExists)
- cname += QUuid::createUuid().toString();
+ className += QUuid::createUuid().toString();
- if (m_registeredWindowClassNames.contains(cname)) // already registered in our list
- return cname;
+ if (m_registeredWindowClassNames.contains(className)) // already registered in our list
+ return className;
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
- wc.style = style;
- wc.lpfnWndProc = proc;
+ wc.style = description.style;
+ wc.lpfnWndProc = description.procedure;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = appInstance;
wc.hCursor = nullptr;
- wc.hbrBackground = brush;
- if (icon) {
+ wc.hbrBackground = description.brush;
+ if (description.hasIcon) {
wc.hIcon = static_cast<HICON>(LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE));
if (wc.hIcon) {
int sw = GetSystemMetrics(SM_CXSMICON);
int sh = GetSystemMetrics(SM_CYSMICON);
wc.hIconSm = static_cast<HICON>(LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, sw, sh, 0));
- } else {
+ }
+ else {
wc.hIcon = static_cast<HICON>(LoadImage(nullptr, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED));
wc.hIconSm = nullptr;
}
- } else {
+ }
+ else {
wc.hIcon = nullptr;
wc.hIconSm = nullptr;
}
wc.lpszMenuName = nullptr;
- wc.lpszClassName = reinterpret_cast<LPCWSTR>(cname.utf16());
+ wc.lpszClassName = reinterpret_cast<LPCWSTR>(className.utf16());
ATOM atom = RegisterClassEx(&wc);
- if (!atom) {
+ if (!atom)
qErrnoWarning("QApplication::regClass: Registering window class '%s' failed.",
- qPrintable(cname));
- }
+ qPrintable(className));
+
+ m_registeredWindowClassNames.insert(className);
+ qCDebug(lcQpaWindowClass).nospace() << __FUNCTION__ << ' ' << className
+ << " style=0x" << Qt::hex << description.style << Qt::dec
+ << " brush=" << description.brush << " icon=" << description.hasIcon << " atom=" << atom;
+ return className;
+}
- m_registeredWindowClassNames.insert(cname);
- qCDebug(lcQpaWindowClass).nospace() << __FUNCTION__ << ' ' << cname
- << " style=0x" << Qt::hex << style << Qt::dec
- << " brush=" << brush << " icon=" << icon << " atom=" << atom;
- return cname;
+QString QWindowsWindowClassRegistry::registerWindowClass(const QWindow *window)
+{
+ return registerWindowClass(QWindowsWindowClassDescription::fromWindow(window, m_proc));
+}
+
+QString QWindowsWindowClassRegistry::registerWindowClass(QString name, WNDPROC procedure)
+{
+ return registerWindowClass(QWindowsWindowClassDescription::fromName(name, procedure));
}
void QWindowsWindowClassRegistry::unregisterWindowClasses()
diff --git a/src/plugins/platforms/windows/qwindowswindowclassregistry.h b/src/plugins/platforms/windows/qwindowswindowclassregistry.h
index d599497abd0..c19b4f616fb 100644
--- a/src/plugins/platforms/windows/qwindowswindowclassregistry.h
+++ b/src/plugins/platforms/windows/qwindowswindowclassregistry.h
@@ -16,6 +16,7 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcQpaWindowClass)
class QWindow;
+struct QWindowsWindowClassDescription;
class QWindowsWindowClassRegistry
{
@@ -26,12 +27,13 @@ public:
static QWindowsWindowClassRegistry *instance();
- static QString classNamePrefix();
-
- QString registerWindowClass(const QWindow *w);
- QString registerWindowClass(QString cname, WNDPROC proc, unsigned style = 0, HBRUSH brush = nullptr, bool icon = false);
+ QString registerWindowClass(const QWindowsWindowClassDescription &description);
+ QString registerWindowClass(const QWindow *window);
+ QString registerWindowClass(QString name, WNDPROC procedure);
private:
+ static QString classNamePrefix();
+
void unregisterWindowClasses();
static QWindowsWindowClassRegistry *m_instance;
diff --git a/src/widgets/widgets/qwidgetanimator.cpp b/src/widgets/widgets/qwidgetanimator.cpp
index 99a051357ee..1216f535b8b 100644
--- a/src/widgets/widgets/qwidgetanimator.cpp
+++ b/src/widgets/widgets/qwidgetanimator.cpp
@@ -53,7 +53,7 @@ void QWidgetAnimator::animate(QWidget *widget, const QRect &_final_geometry, boo
//If the QStyle has animations, animate
if (const int animationDuration = widget->style()->styleHint(QStyle::SH_Widget_Animation_Duration, nullptr, widget)) {
AnimationMap::const_iterator it = m_animation_map.constFind(widget);
- if (it != m_animation_map.constEnd() && (*it)->endValue().toRect() == final_geometry)
+ if (it != m_animation_map.constEnd() && *it && (*it)->endValue().toRect() == final_geometry)
return;
QPropertyAnimation *anim = new QPropertyAnimation(widget, "geometry", widget);
@@ -76,7 +76,8 @@ void QWidgetAnimator::animate(QWidget *widget, const QRect &_final_geometry, boo
bool QWidgetAnimator::animating() const
{
- return !m_animation_map.isEmpty();
+ auto isActiveAnimation = [](const QPointer<QPropertyAnimation> &p) { return !p.isNull(); };
+ return !std::all_of(m_animation_map.begin(), m_animation_map.end(), isActiveAnimation);
}
QT_END_NAMESPACE
diff --git a/tests/auto/corelib/platform/android/tst_android.cpp b/tests/auto/corelib/platform/android/tst_android.cpp
index 3665f100a61..b4bb0323f8a 100644
--- a/tests/auto/corelib/platform/android/tst_android.cpp
+++ b/tests/auto/corelib/platform/android/tst_android.cpp
@@ -430,6 +430,8 @@ void tst_Android::testFullScreenDimensions()
widget.showNormal();
}
+ // TODO needs fix to work in local and CI on same fashion
+ const bool runsOnCI = qgetenv("QTEST_ENVIRONMENT").split(' ').contains("ci");
{
// Translucent
// available geometry == full display size (system bars visible but drawable under)
@@ -437,14 +439,11 @@ void tst_Android::testFullScreenDimensions()
widget.show();
QCoreApplication::processEvents();
QTRY_COMPARE(screen->availableGeometry().width(), realSize.getField<jint>("x"));
- QTRY_COMPARE(screen->availableGeometry().height(), realSize.getField<jint>("y"));
-
- QTRY_COMPARE(screen->geometry().width(), realSize.getField<jint>("x"));
- // TODO needs fix to work in local and CI on same fashion
- const bool runsOnCI = qgetenv("QTEST_ENVIRONMENT").split(' ').contains("ci");
if ((sdkVersion > __ANDROID_API_V__) && runsOnCI)
QEXPECT_FAIL("", "Fails on Android 16 (QTBUG-141712).", Continue);
+ QTRY_COMPARE(screen->availableGeometry().height(), realSize.getField<jint>("y"));
+ QTRY_COMPARE(screen->geometry().width(), realSize.getField<jint>("x"));
QTRY_COMPARE(screen->geometry().height(), realSize.getField<jint>("y"));
widget.showNormal();
}
@@ -455,6 +454,8 @@ void tst_Android::testFullScreenDimensions()
widget.showMaximized();
QCoreApplication::processEvents();
QTRY_COMPARE(screen->availableGeometry().width(), realSize.getField<jint>("x"));
+ if ((sdkVersion > __ANDROID_API_V__) && runsOnCI)
+ QEXPECT_FAIL("", "Fails on Android 16 (QTBUG-141712).", Continue);
QTRY_COMPARE(screen->availableGeometry().height(), realSize.getField<jint>("y"));
QTRY_COMPARE(screen->geometry().width(), realSize.getField<jint>("x"));
diff --git a/tests/auto/gui/kernel/qguieventdispatcher/BLACKLIST b/tests/auto/gui/kernel/qguieventdispatcher/BLACKLIST
new file mode 100644
index 00000000000..a8f73d73f4d
--- /dev/null
+++ b/tests/auto/gui/kernel/qguieventdispatcher/BLACKLIST
@@ -0,0 +1,2 @@
+[postEventFromThread]
+macos-26 developer-build # QTBUG-142185
diff --git a/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.cpp b/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.cpp
index 1e49847c97f..484c28a484b 100644
--- a/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.cpp
+++ b/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.cpp
@@ -9,6 +9,12 @@
#include <emscripten.h>
#include <emscripten/threading.h>
+#if QT_CONFIG(wasm_jspi)
+# define QT_WASM_EMSCRIPTEN_ASYNC ,emscripten::async()
+#else
+# define QT_WASM_EMSCRIPTEN_ASYNC
+#endif
+
namespace QtWasmTest {
namespace {
QObject *g_testObject = nullptr;
@@ -127,7 +133,7 @@ void passTest()
EMSCRIPTEN_BINDINGS(qtwebtestrunner) {
emscripten::function("cleanupTestCase", &cleanupTestCase);
emscripten::function("getTestFunctions", &getTestFunctions);
- emscripten::function("runTestFunction", &runTestFunction, emscripten::async());
+ emscripten::function("runTestFunction", &runTestFunction QT_WASM_EMSCRIPTEN_ASYNC);
emscripten::function("qtWasmFail", &failTest);
emscripten::function("qtWasmPass", &passTest);
}