diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2016-03-21 16:14:42 +0000 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2016-03-21 18:40:23 +0000 |
commit | f9e746959b9c7acbc080c410fe5cb5dff127c5dd (patch) | |
tree | b602fcc7baaa934f3f8fbd338f4dae6c906c1ede /src | |
parent | 686e37b1b7c40d0e864ab47165be3a0d4faa9a68 (diff) | |
parent | 6cb8121a44ee0f94f2c9fcb075d1d3c802d8c5c7 (diff) | |
download | qtbase-f9e746959b9c7acbc080c410fe5cb5dff127c5dd.tar.gz |
Merge "Merge remote-tracking branch 'origin/5.6' into 5.7" into refs/staging/5.7
Diffstat (limited to 'src')
158 files changed, 1433 insertions, 863 deletions
diff --git a/src/3rdparty/libpng/ANNOUNCE b/src/3rdparty/libpng/ANNOUNCE index 9f1b665834..4dae783b55 100644 --- a/src/3rdparty/libpng/ANNOUNCE +++ b/src/3rdparty/libpng/ANNOUNCE @@ -1,4 +1,4 @@ -Libpng 1.6.19 - November 12, 2015 +Libpng 1.6.20 - December 3, 2015 This is a public release of libpng, intended for use in production codes. @@ -7,104 +7,41 @@ Files available for download: Source files with LF line endings (for Unix/Linux) and with a "configure" script - libpng-1.6.19.tar.xz (LZMA-compressed, recommended) - libpng-1.6.19.tar.gz + libpng-1.6.20.tar.xz (LZMA-compressed, recommended) + libpng-1.6.20.tar.gz Source files with CRLF line endings (for Windows), without the "configure" script - lpng1619.7z (LZMA-compressed, recommended) - lpng1619.zip + /scratch/glennrp/Libpng16/lpng1620.7z (LZMA-compressed, recommended) + /scratch/glennrp/Libpng16/lpng1620.zip Other information: - libpng-1.6.19-README.txt - libpng-1.6.19-LICENSE.txt - libpng-1.6.19-*.asc (armored detached GPG signatures) - -Changes since the last public release (1.6.18): - - Updated obsolete information about the simplified API macros in the - manual pages (Bug report by Arc Riley). - Avoid potentially dereferencing NULL info_ptr in png_info_init_3(). - Rearranged png.h to put the major sections in the same order as - in libpng17. - Eliminated unused PNG_COST_SHIFT, PNG_WEIGHT_SHIFT, PNG_COST_FACTOR, and - PNG_WEIGHT_FACTOR macros. - Suppressed some warnings from the Borland C++ 5.5.1/5.82 compiler - (Bug report by Viktor Szakats). Several warnings remain and are - unavoidable, where we test for overflow. - Fixed potential leak of png_pixels in contrib/pngminus/pnm2png.c - Fixed uninitialized variable in contrib/gregbook/rpng2-x.c - Moved config.h.in~ from the "libpng_autotools_files" list to the - "libpng_autotools_extra" list in autogen.sh because it was causing a - false positive for missing files (bug report by Robert C. Seacord). - Removed unreachable "break" statements in png.c, pngread.c, and pngrtran.c - to suppress clang warnings (Bug report by Viktor Szakats). - Fixed some bad links in the man page. - Changed "n bit" to "n-bit" in comments. - Added signed/unsigned 16-bit safety net. This removes the dubious - 0x8000 flag definitions on 16-bit systems. They aren't supported - yet the defs *probably* work, however it seems much safer to do this - and be advised if anyone, contrary to advice, is building libpng 1.6 - on a 16-bit system. It also adds back various switch default clauses - for GCC; GCC errors out if they are not present (with an appropriately - high level of warnings). - Safely convert num_bytes to a png_byte in png_set_sig_bytes() (Robert - Seacord). - Fixed the recently reported 1's complement security issue by replacing - the value that is illegal in the PNG spec, in both signed and unsigned - values, with 0. Illegal unsigned values (anything greater than or equal - to 0x80000000) can still pass through, but since these are not illegal - in ANSI-C (unlike 0x80000000 in the signed case) the checking that - occurs later can catch them (John Bowler). - Fixed png_save_int_32 when int is not 2's complement (John Bowler). - Updated libpng16 with all the recent test changes from libpng17, - including changes to pngvalid.c to ensure that the original, - distributed, version of contrib/visupng/cexcept.h can be used - (John Bowler). - pngvalid contains the correction to the use of SAVE/STORE_ - UNKNOWN_CHUNKS; a bug revealed by changes in libpng 1.7. More - tests contain the --strict option to detect warnings and the - pngvalid-standard test has been corrected so that it does not - turn on progressive-read. There is a separate test which does - that. (John Bowler) - Also made some signed/unsigned fixes. - Make pngstest error limits version specific. Splitting the machine - generated error structs out to a file allows the values to be updated - without changing pngstest.c itself. Since libpng 1.6 and 1.7 have - slightly different error limits this simplifies maintenance. The - makepngs.sh script has also been updated to more accurately reflect - current problems in libpng 1.7 (John Bowler). - Incorporated new test PNG files into make check. tests/pngstest-* - are changed so that the new test files are divided into 8 groups by - gamma and alpha channel. These tests have considerably better code - and pixel-value coverage than contrib/pngsuite; however,coverage is - still incomplete (John Bowler). - Removed the '--strict' in 1.6 because of the double-gamma-correction - warning, updated pngstest-errors.h for the errors detected with the - new contrib/testspngs PNG test files (John Bowler). - Worked around rgb-to-gray issues in libpng 1.6. The previous - attempts to ignore the errors in the code aren't quite enough to - deal with the 'channel selection' encoding added to libpng 1.7; abort. - Fixed 'pow' macros in pngvalid.c. It is legal for 'pow' to be a - macro, therefore the argument list cannot contain preprocessing - directives. Make sure pow is a function where this happens. This is - a minimal safe fix, the issue only arises in non-performance-critical - code (bug report by Curtis Leach, fix by John Bowler). - Added sPLT support to pngtest.c - Prevent setting or writing over-length PLTE chunk (Cosmin Truta). - Silently truncate over-length PLTE chunk while reading. - Libpng incorrectly calculated the output rowbytes when the application - decreased either the number of channels or the bit depth (or both) in - a user transform. This was safe; libpng overallocated buffer space - (potentially by quite a lot; up to 4 times the amount required) but, - from 1.5.4 on, resulted in a png_error (John Bowler). - Fixed some inconsequential cut-and-paste typos in png_set_cHRM_XYZ_fixed(). - Clarified COPYRIGHT information to state explicitly that versions - are derived from previous versions. - Removed much of the long list of previous versions from png.h and - libpng.3. + libpng-1.6.20-README.txt + libpng-1.6.20-LICENSE.txt + libpng-1.6.20-*.asc (armored detached GPG signatures) + +Changes since the last public release (1.6.19): + Avoid potential pointer overflow/underflow in png_handle_sPLT() and + png_handle_pCAL() (Bug report by John Regehr). + Fixed incorrect implementation of png_set_PLTE() that uses png_ptr + not info_ptr, that left png_set_PLTE() open to the CVE-2015-8126 + vulnerability. + Backported tests from libpng-1.7.0beta69. + Fixed an error in handling of bad zlib CMINFO field in pngfix, found by + American Fuzzy Lop, reported by Brian Carpenter. inflate() doesn't + immediately fault a bad CMINFO field; instead a 'too far back' error + happens later (at least some times). pngfix failed to limit CMINFO to + the allowed values but then assumed that window_bits was in range, + triggering an assert. The bug is mostly harmless; the PNG file cannot + be fixed. + In libpng 1.6 zlib initialization was changed to use the window size + in the zlib stream, not a fixed value. This causes some invalid images, + where CINFO is too large, to display 'correctly' if the rest of the + data is valid. This provides a workaround for zlib versions where the + error arises (ones that support the API change to use the window size + in the stream). Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit diff --git a/src/3rdparty/libpng/CHANGES b/src/3rdparty/libpng/CHANGES index 2e4d2bb292..28094fd26c 100644 --- a/src/3rdparty/libpng/CHANGES +++ b/src/3rdparty/libpng/CHANGES @@ -5409,11 +5409,43 @@ Version 1.6.19rc03 [November 3, 2015] Version 1.6.19rc04 [November 5, 2015] Fixed new bug with CRC error after reading an over-length palette - (bug report by Cosmin Truta). + (bug report by Cosmin Truta) (CVE-2015-8126). Version 1.6.19 [November 12, 2015] Cleaned up coding style in png_handle_PLTE(). +Version 1.6.20beta01 [November 20, 2015] + Avoid potential pointer overflow/underflow in png_handle_sPLT() and + png_handle_pCAL() (Bug report by John Regehr). + +Version 1.6.20beta02 [November 23, 2015] + Fixed incorrect implementation of png_set_PLTE() that uses png_ptr + not info_ptr, that left png_set_PLTE() open to the CVE-2015-8126 + vulnerability. + +Version 1.6.20beta03 [November 24, 2015] + Backported tests from libpng-1.7.0beta69. + +Version 1.6.20rc01 [November 26, 2015] + Fixed an error in handling of bad zlib CMINFO field in pngfix, found by + American Fuzzy Lop, reported by Brian Carpenter. inflate() doesn't + immediately fault a bad CMINFO field; instead a 'too far back' error + happens later (at least some times). pngfix failed to limit CMINFO to + the allowed values but then assumed that window_bits was in range, + triggering an assert. The bug is mostly harmless; the PNG file cannot + be fixed. + +Version 1.6.20rc02 [November 29, 2015] + In libpng 1.6 zlib initialization was changed to use the window size + in the zlib stream, not a fixed value. This causes some invalid images, + where CINFO is too large, to display 'correctly' if the rest of the + data is valid. This provides a workaround for zlib versions where the + error arises (ones that support the API change to use the window size + in the stream). + +Version 1.6.20 [December 3, 2015] + No changes. + Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement diff --git a/src/3rdparty/libpng/LICENSE b/src/3rdparty/libpng/LICENSE index 11f6ffe5db..82dbe117f6 100644 --- a/src/3rdparty/libpng/LICENSE +++ b/src/3rdparty/libpng/LICENSE @@ -10,7 +10,7 @@ this sentence. This code is released under the libpng license. -libpng versions 1.0.7, July 1, 2000, through 1.6.19, November 12, 2015, are +libpng versions 1.0.7, July 1, 2000, through 1.6.20, December 3, 2015, are Copyright (c) 2000-2002, 2004, 2006-2015 Glenn Randers-Pehrson, are derived from libpng-1.0.6, and are distributed according to the same disclaimer and license as libpng-1.0.6 with the following individuals @@ -109,4 +109,4 @@ the additional disclaimers inserted at version 1.0.7. Glenn Randers-Pehrson glennrp at users.sourceforge.net -November 12, 2015 +December 3, 2015 diff --git a/src/3rdparty/libpng/README b/src/3rdparty/libpng/README index 17484e0fd7..59f1f918ae 100644 --- a/src/3rdparty/libpng/README +++ b/src/3rdparty/libpng/README @@ -1,4 +1,4 @@ -README for libpng version 1.6.19 - November 12, 2015 (shared library 16.0) +README for libpng version 1.6.20 - December 3, 2015 (shared library 16.0) See the note about version numbers near the top of png.h See INSTALL for instructions on how to install libpng. diff --git a/src/3rdparty/libpng/libpng-manual.txt b/src/3rdparty/libpng/libpng-manual.txt index bc7a441cf2..87eeb2b583 100644 --- a/src/3rdparty/libpng/libpng-manual.txt +++ b/src/3rdparty/libpng/libpng-manual.txt @@ -1,6 +1,6 @@ libpng-manual.txt - A description on how to use and modify libpng - libpng version 1.6.19 - November 12, 2015 + libpng version 1.6.20 - December 3, 2015 Updated and distributed by Glenn Randers-Pehrson <glennrp at users.sourceforge.net> Copyright (c) 1998-2015 Glenn Randers-Pehrson @@ -11,7 +11,7 @@ libpng-manual.txt - A description on how to use and modify libpng Based on: - libpng versions 0.97, January 1998, through 1.6.19 - November 12, 2015 + libpng versions 0.97, January 1998, through 1.6.20 - December 3, 2015 Updated and distributed by Glenn Randers-Pehrson Copyright (c) 1998-2015 Glenn Randers-Pehrson @@ -2960,6 +2960,7 @@ width, height, bit_depth, and color_type must be the same in each call. (array of png_color) num_palette - number of entries in the palette + png_set_gAMA(png_ptr, info_ptr, file_gamma); png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma); @@ -4897,7 +4898,7 @@ a set of "safe" limits is applied in pngpriv.h. These can be overridden by application calls to png_set_user_limits(), png_set_user_chunk_cache_max(), and/or png_set_user_malloc_max() that increase or decrease the limits. Also, in libpng-1.5.10 the default width and height limits were increased -from 1,000,000 to 0x7ffffff (i.e., made unlimited). Therefore, the +from 1,000,000 to 0x7fffffff (i.e., made unlimited). Therefore, the limits are now default safe png_user_width_max 0x7fffffff 1,000,000 @@ -5323,7 +5324,7 @@ Since the PNG Development group is an ad-hoc body, we can't make an official declaration. This is your unofficial assurance that libpng from version 0.71 and -upward through 1.6.19 are Y2K compliant. It is my belief that earlier +upward through 1.6.20 are Y2K compliant. It is my belief that earlier versions were also Y2K compliant. Libpng only has two year fields. One is a 2-byte unsigned integer diff --git a/src/3rdparty/libpng/png.c b/src/3rdparty/libpng/png.c index 6fcfad72ec..c183e3f8fa 100644 --- a/src/3rdparty/libpng/png.c +++ b/src/3rdparty/libpng/png.c @@ -14,7 +14,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_19 Your_png_h_is_not_version_1_6_19; +typedef png_libpng_version_1_6_20 Your_png_h_is_not_version_1_6_20; /* Tells libpng that we have already handled the first "num_bytes" bytes * of the PNG file signature. If the PNG data is embedded into another @@ -775,13 +775,13 @@ png_get_copyright(png_const_structrp png_ptr) #else # ifdef __STDC__ return PNG_STRING_NEWLINE \ - "libpng version 1.6.19 - November 12, 2015" PNG_STRING_NEWLINE \ + "libpng version 1.6.20 - December 3, 2015" PNG_STRING_NEWLINE \ "Copyright (c) 1998-2015 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ PNG_STRING_NEWLINE; # else - return "libpng version 1.6.19 - November 12, 2015\ + return "libpng version 1.6.20 - December 3, 2015\ Copyright (c) 1998-2015 Glenn Randers-Pehrson\ Copyright (c) 1996-1997 Andreas Dilger\ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; @@ -2343,7 +2343,7 @@ png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, * Fall through to "no match". */ png_chunk_report(png_ptr, - "Not recognizing known sRGB profile that has been edited", + "Not recognizing known sRGB profile that has been edited", PNG_CHUNK_WARNING); break; # endif diff --git a/src/3rdparty/libpng/png.h b/src/3rdparty/libpng/png.h index c83051b1ca..4d03dfc136 100644 --- a/src/3rdparty/libpng/png.h +++ b/src/3rdparty/libpng/png.h @@ -1,7 +1,7 @@ /* png.h - header file for PNG reference library * - * libpng version 1.6.19, November 12, 2015 + * libpng version 1.6.20, December 3, 2015 * * Copyright (c) 1998-2015 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) @@ -12,7 +12,8 @@ * Authors and maintainers: * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.6.19, November 12, 2015: Glenn + * libpng versions 0.97, January 1998, through 1.6.20, December 3, 2015: + * Glenn Randers-Pehrson. * See also "Contributing Authors", below. */ @@ -24,7 +25,7 @@ * * This code is released under the libpng license. * - * libpng versions 1.0.7, July 1, 2000, through 1.6.19, November 12, 2015, are + * libpng versions 1.0.7, July 1, 2000, through 1.6.20, December 3, 2015, are * Copyright (c) 2000-2002, 2004, 2006-2015 Glenn Randers-Pehrson, are * derived from libpng-1.0.6, and are distributed according to the same * disclaimer and license as libpng-1.0.6 with the following individuals @@ -185,7 +186,7 @@ * ... * 1.5.23 15 10523 15.so.15.23[.0] * ... - * 1.6.19 16 10619 16.so.16.19[.0] + * 1.6.20 16 10620 16.so.16.20[.0] * * Henceforth the source version will match the shared-library major * and minor numbers; the shared-library major version number will be @@ -213,13 +214,13 @@ * Y2K compliance in libpng: * ========================= * - * November 12, 2015 + * December 3, 2015 * * Since the PNG Development group is an ad-hoc body, we can't make * an official declaration. * * This is your unofficial assurance that libpng from version 0.71 and - * upward through 1.6.19 are Y2K compliant. It is my belief that + * upward through 1.6.20 are Y2K compliant. It is my belief that * earlier versions were also Y2K compliant. * * Libpng only has two year fields. One is a 2-byte unsigned integer @@ -281,9 +282,9 @@ */ /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.6.19" +#define PNG_LIBPNG_VER_STRING "1.6.20" #define PNG_HEADER_VERSION_STRING \ - " libpng version 1.6.19 - November 12, 2015\n" + " libpng version 1.6.20 - December 3, 2015\n" #define PNG_LIBPNG_VER_SONUM 16 #define PNG_LIBPNG_VER_DLLNUM 16 @@ -291,7 +292,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 19 +#define PNG_LIBPNG_VER_RELEASE 20 /* This should match the numeric part of the final component of * PNG_LIBPNG_VER_STRING, omitting any leading zero: @@ -322,7 +323,7 @@ * version 1.0.0 was mis-numbered 100 instead of 10000). From * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release */ -#define PNG_LIBPNG_VER 10619 /* 1.6.19 */ +#define PNG_LIBPNG_VER 10620 /* 1.6.20 */ /* Library configuration: these options cannot be changed after * the library has been built. @@ -432,7 +433,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_19; +typedef char* png_libpng_version_1_6_20; /* 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 f1b795b478..92f250000c 100644 --- a/src/3rdparty/libpng/pngconf.h +++ b/src/3rdparty/libpng/pngconf.h @@ -1,7 +1,7 @@ /* pngconf.h - machine configurable file for libpng * - * libpng version 1.6.19, July 23, 2015 + * libpng version 1.6.20, December 3, 2015 * * Copyright (c) 1998-2015 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) diff --git a/src/3rdparty/libpng/pngerror.c b/src/3rdparty/libpng/pngerror.c index 0781866a89..bdb959ee51 100644 --- a/src/3rdparty/libpng/pngerror.c +++ b/src/3rdparty/libpng/pngerror.c @@ -768,7 +768,7 @@ png_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN) /* If control reaches this point, png_longjmp() must not return. The only * choice is to terminate the whole process (or maybe the thread); to do - * this the ANSI-C abort() function is used unless a different method is + * this the ANSI-C abort() function is used unless a different method is * implemented by overriding the default configuration setting for * PNG_ABORT(). */ diff --git a/src/3rdparty/libpng/pnginfo.h b/src/3rdparty/libpng/pnginfo.h index c8c874dd1e..4bd264b869 100644 --- a/src/3rdparty/libpng/pnginfo.h +++ b/src/3rdparty/libpng/pnginfo.h @@ -223,7 +223,7 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) /* Storage for unknown chunks that the library doesn't recognize. */ png_unknown_chunkp unknown_chunks; - /* The type of this field is limited by the type of + /* The type of this field is limited by the type of * png_struct::user_chunk_cache_max, else overflow can occur. */ int unknown_chunks_num; diff --git a/src/3rdparty/libpng/pnglibconf.h b/src/3rdparty/libpng/pnglibconf.h index 8b6da9eb2c..0dba5055f7 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.19, July 23, 2015 */ +/* libpng version 1.6.20 - December 3, 2015 */ /* Copyright (c) 1998-2014 Glenn Randers-Pehrson */ diff --git a/src/3rdparty/libpng/pngpread.c b/src/3rdparty/libpng/pngpread.c index 9f68f99023..89ffc4018f 100644 --- a/src/3rdparty/libpng/pngpread.c +++ b/src/3rdparty/libpng/pngpread.c @@ -133,7 +133,7 @@ png_process_some_data(png_structrp png_ptr, png_inforp info_ptr) void /* PRIVATE */ png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr) { - png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */ + png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */ num_to_check = 8 - num_checked; if (png_ptr->buffer_size < num_to_check) @@ -662,7 +662,7 @@ png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer, * change the current behavior (see comments in inflate.c * for why this doesn't happen at present with zlib 1.2.5). */ - ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH); + ret = PNG_INFLATE(png_ptr, Z_SYNC_FLUSH); /* Check for any failure before proceeding. */ if (ret != Z_OK && ret != Z_STREAM_END) diff --git a/src/3rdparty/libpng/pngpriv.h b/src/3rdparty/libpng/pngpriv.h index f7a45477a4..c06deee68d 100644 --- a/src/3rdparty/libpng/pngpriv.h +++ b/src/3rdparty/libpng/pngpriv.h @@ -1229,6 +1229,14 @@ PNG_INTERNAL_FUNCTION(void,png_read_finish_row,(png_structrp png_ptr), /* Initialize the row buffers, etc. */ PNG_INTERNAL_FUNCTION(void,png_read_start_row,(png_structrp png_ptr),PNG_EMPTY); +#if PNG_ZLIB_VERNUM >= 0x1240 +PNG_INTERNAL_FUNCTION(int,png_zlib_inflate,(png_structrp png_ptr, int flush), + PNG_EMPTY); +# define PNG_INFLATE(pp, flush) png_zlib_inflate(pp, flush) +#else /* Zlib < 1.2.4 */ +# define PNG_INFLATE(pp, flush) inflate(&(pp)->zstream, flush) +#endif /* Zlib < 1.2.4 */ + #ifdef PNG_READ_TRANSFORMS_SUPPORTED /* Optional call to update the users info structure */ PNG_INTERNAL_FUNCTION(void,png_read_transform_info,(png_structrp png_ptr, diff --git a/src/3rdparty/libpng/pngread.c b/src/3rdparty/libpng/pngread.c index 48aae84881..9cb4d2e41d 100644 --- a/src/3rdparty/libpng/pngread.c +++ b/src/3rdparty/libpng/pngread.c @@ -2838,7 +2838,6 @@ png_image_read_colormap(png_voidp argument) default: png_error(png_ptr, "invalid PNG color type"); /*NOT REACHED*/ - break; } /* Now deal with the output processing */ diff --git a/src/3rdparty/libpng/pngrutil.c b/src/3rdparty/libpng/pngrutil.c index ee584a8c40..6189251352 100644 --- a/src/3rdparty/libpng/pngrutil.c +++ b/src/3rdparty/libpng/pngrutil.c @@ -1,7 +1,7 @@ /* pngrutil.c - utilities to read a PNG file * - * Last changed in libpng 1.6.19 [November 12, 2015] + * Last changed in libpng 1.6.20 [December 3, 2015] * Copyright (c) 1998-2015 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -377,10 +377,16 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) if (((png_ptr->options >> PNG_MAXIMUM_INFLATE_WINDOW) & 3) == PNG_OPTION_ON) + { window_bits = 15; + png_ptr->zstream_start = 0; /* fixed window size */ + } else + { window_bits = 0; + png_ptr->zstream_start = 1; + } # else # define window_bits 0 # endif @@ -429,6 +435,31 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) #endif } +#if PNG_ZLIB_VERNUM >= 0x1240 +/* Handle the start of the inflate stream if we called inflateInit2(strm,0); + * in this case some zlib versions skip validation of the CINFO field and, in + * certain circumstances, libpng may end up displaying an invalid image, in + * contrast to implementations that call zlib in the normal way (e.g. libpng + * 1.5). + */ +int /* PRIVATE */ +png_zlib_inflate(png_structrp png_ptr, int flush) +{ + if (png_ptr->zstream_start && png_ptr->zstream.avail_in > 0) + { + if ((*png_ptr->zstream.next_in >> 4) > 7) + { + png_ptr->zstream.msg = "invalid window size (libpng)"; + return Z_DATA_ERROR; + } + + png_ptr->zstream_start = 0; + } + + return inflate(&png_ptr->zstream, flush); +} +#endif /* Zlib >= 1.2.4 */ + #ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED /* png_inflate now returns zlib error codes including Z_OK and Z_STREAM_END to * allow the caller to do multiple calls if required. If the 'finish' flag is @@ -522,7 +553,7 @@ png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish, * the previous chunk of input data. Tell zlib if we have reached the * end of the output buffer. */ - ret = inflate(&png_ptr->zstream, avail_out > 0 ? Z_NO_FLUSH : + ret = PNG_INFLATE(png_ptr, avail_out > 0 ? Z_NO_FLUSH : (finish ? Z_FINISH : Z_SYNC_FLUSH)); } while (ret == Z_OK); @@ -771,7 +802,7 @@ png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size, * the available output is produced; this allows reading of truncated * streams. */ - ret = inflate(&png_ptr->zstream, + ret = PNG_INFLATE(png_ptr, *chunk_bytes > 0 ? Z_NO_FLUSH : (finish ? Z_FINISH : Z_SYNC_FLUSH)); } while (ret == Z_OK && (*out_size > 0 || png_ptr->zstream.avail_out > 0)); @@ -1670,7 +1701,7 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) ++entry_start; /* A sample depth should follow the separator, and we should be on it */ - if (entry_start > buffer + length - 2) + if (length < 2U || entry_start > buffer + (length - 2U)) { png_warning(png_ptr, "malformed sPLT chunk"); return; @@ -2174,7 +2205,7 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) /* We need to have at least 12 bytes after the purpose string * in order to get the parameter information. */ - if (endptr <= buf + 12) + if (endptr - buf <= 12) { png_chunk_benign_error(png_ptr, "invalid"); return; @@ -4039,7 +4070,7 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output, * * TODO: deal more elegantly with truncated IDAT lists. */ - ret = inflate(&png_ptr->zstream, Z_NO_FLUSH); + ret = PNG_INFLATE(png_ptr, Z_NO_FLUSH); /* Take the unconsumed output back. */ if (output != NULL) diff --git a/src/3rdparty/libpng/pngset.c b/src/3rdparty/libpng/pngset.c index 05a2134dbb..8fd7965fca 100644 --- a/src/3rdparty/libpng/pngset.c +++ b/src/3rdparty/libpng/pngset.c @@ -520,8 +520,8 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr, if (png_ptr == NULL || info_ptr == NULL) return; - max_palette_length = (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ? - (1 << png_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH; + max_palette_length = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ? + (1 << info_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH; if (num_palette < 0 || num_palette > (int) max_palette_length) { @@ -1573,7 +1573,7 @@ png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max, { /* Images with dimensions larger than these limits will be * rejected by png_set_IHDR(). To accept any PNG datastream - * regardless of dimensions, set both limits to 0x7ffffff. + * regardless of dimensions, set both limits to 0x7fffffff. */ if (png_ptr == NULL) return; diff --git a/src/3rdparty/libpng/pngstruct.h b/src/3rdparty/libpng/pngstruct.h index c8c0e46e8b..d0bcc7914a 100644 --- a/src/3rdparty/libpng/pngstruct.h +++ b/src/3rdparty/libpng/pngstruct.h @@ -263,6 +263,9 @@ struct png_struct_def /* pixel depth used for the row buffers */ png_byte transformed_pixel_depth; /* pixel depth after read/write transforms */ +#if PNG_ZLIB_VERNUM >= 0x1240 + png_byte zstream_start; /* at start of an input zlib stream */ +#endif /* Zlib >= 1.2.4 */ #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) png_uint_16 filler; /* filler bytes for pixel expansion */ #endif diff --git a/src/3rdparty/libpng/pngwutil.c b/src/3rdparty/libpng/pngwutil.c index adc4729c24..0ee102b5fb 100644 --- a/src/3rdparty/libpng/pngwutil.c +++ b/src/3rdparty/libpng/pngwutil.c @@ -2563,7 +2563,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) if (filter_to_do == PNG_FILTER_SUB) /* It's the only filter so no testing is needed */ { - (void) png_setup_sub_row(png_ptr, bpp, row_bytes, mins); + (void) png_setup_sub_row(png_ptr, bpp, row_bytes, mins); best_row = png_ptr->try_row; } @@ -2572,7 +2572,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) png_size_t sum; png_size_t lmins = mins; - sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins); + sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins); if (sum < mins) { @@ -2598,7 +2598,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) png_size_t sum; png_size_t lmins = mins; - sum = png_setup_up_row(png_ptr, row_bytes, lmins); + sum = png_setup_up_row(png_ptr, row_bytes, lmins); if (sum < mins) { diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 46cfe9e2b9..86aa9b9e7a 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -98,6 +98,11 @@ extern char *__progname; #if defined(Q_OS_LINUX) && (defined(__GLIBC__) || QT_HAS_INCLUDE(<sys/syscall.h>)) # include <sys/syscall.h> + +# if defined(Q_OS_ANDROID) && !defined(SYS_gettid) +# define SYS_gettid __NR_gettid +# endif + static long qt_gettid() { // no error handling diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h index 1200c3b5a5..e709050011 100644 --- a/src/corelib/global/qtypeinfo.h +++ b/src/corelib/global/qtypeinfo.h @@ -118,14 +118,14 @@ public: */ // apply defaults for a generic QTypeInfo<T> that didn't provide the new values template <typename T, typename = void> -struct QTypeInfoQuery : QTypeInfo<T> +struct QTypeInfoQuery : public QTypeInfo<T> { enum { isRelocatable = !QTypeInfo<T>::isStatic }; }; // if QTypeInfo<T>::isRelocatable exists, use it template <typename T> -struct QTypeInfoQuery<T, typename QtPrivate::QEnableIf<QTypeInfo<T>::isRelocatable || true>::Type> : QTypeInfo<T> +struct QTypeInfoQuery<T, typename QtPrivate::QEnableIf<QTypeInfo<T>::isRelocatable || true>::Type> : public QTypeInfo<T> {}; /*! diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index ef787832a4..5d8b567c8c 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -684,10 +684,7 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) QIncrementalSleepTimer timer(msecs); forever { - // Check if we have any data pending: the pipe writer has - // bytes waiting to written, or it has written data since the - // last time we called stdinChannel.writer->waitForWrite(). - bool pendingDataInPipe = stdinChannel.writer && (stdinChannel.writer->bytesToWrite() || stdinChannel.writer->hadWritten()); + bool pendingDataInPipe = stdinChannel.writer && stdinChannel.writer->bytesToWrite(); // If we don't have pending data, and our write buffer is // empty, we fail. @@ -815,7 +812,6 @@ qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen) stdinChannel.writer = new QWindowsPipeWriter(stdinChannel.pipe[1], q); QObjectPrivate::connect(stdinChannel.writer, &QWindowsPipeWriter::canWrite, this, &QProcessPrivate::_q_canWrite); - stdinChannel.writer->start(); } return stdinChannel.writer->write(data, maxlen); diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp index 9e3cb9ab4d..9bd5a9e3b6 100644 --- a/src/corelib/io/qstandardpaths_win.cpp +++ b/src/corelib/io/qstandardpaths_win.cpp @@ -117,6 +117,7 @@ static inline void appendTestMode(QString &path) // Map QStandardPaths::StandardLocation to CLSID of SHGetSpecialFolderPath() static int writableSpecialFolderClsid(QStandardPaths::StandardLocation type) { +#ifndef Q_OS_WINCE static const int clsids[] = { CSIDL_DESKTOPDIRECTORY, // DesktopLocation CSIDL_PERSONAL, // DocumentsLocation @@ -136,6 +137,27 @@ static int writableSpecialFolderClsid(QStandardPaths::StandardLocation type) CSIDL_APPDATA, // AppDataLocation ("Roaming" path) CSIDL_LOCAL_APPDATA, // AppConfigLocation ("Local" path) }; +#else // !Q_OS_WINCE + static const int clsids[] = { + CSIDL_DESKTOPDIRECTORY, // DesktopLocation + CSIDL_PERSONAL, // DocumentsLocation + CSIDL_FONTS, // FontsLocation + CSIDL_PROGRAMS, // ApplicationsLocation + CSIDL_MYMUSIC, // MusicLocation + CSIDL_MYVIDEO, // MoviesLocation + CSIDL_MYPICTURES, // PicturesLocation + -1, -1, // TempLocation/HomeLocation + CSIDL_APPDATA, // AppLocalDataLocation, AppLocalDataLocation = DataLocation + -1, // CacheLocation + CSIDL_APPDATA, // GenericDataLocation + -1, // RuntimeLocation + CSIDL_APPDATA, // ConfigLocation + -1, -1, // DownloadLocation/GenericCacheLocation + CSIDL_APPDATA, // GenericConfigLocation + CSIDL_APPDATA, // AppDataLocation + CSIDL_APPDATA, // AppConfigLocation + }; +#endif // Q_OS_WINCE Q_STATIC_ASSERT(sizeof(clsids) / sizeof(clsids[0]) == size_t(QStandardPaths::AppConfigLocation + 1)); return size_t(type) < sizeof(clsids) / sizeof(clsids[0]) ? clsids[type] : -1; diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp index 95232385b2..15fb276be9 100644 --- a/src/corelib/io/qwindowspipereader.cpp +++ b/src/corelib/io/qwindowspipereader.cpp @@ -38,28 +38,40 @@ ****************************************************************************/ #include "qwindowspipereader_p.h" -#include "qwinoverlappedionotifier_p.h" -#include <qdebug.h> +#include "qiodevice_p.h" #include <qelapsedtimer.h> -#include <qeventloop.h> QT_BEGIN_NAMESPACE +QWindowsPipeReader::Overlapped::Overlapped(QWindowsPipeReader *reader) + : pipeReader(reader) +{ +} + +void QWindowsPipeReader::Overlapped::clear() +{ + ZeroMemory(this, sizeof(OVERLAPPED)); +} + + QWindowsPipeReader::QWindowsPipeReader(QObject *parent) : QObject(parent), handle(INVALID_HANDLE_VALUE), + overlapped(this), readBufferMaxSize(0), actualReadBufferSize(0), stopped(true), readSequenceStarted(false), + notifiedCalled(false), pipeBroken(false), - readyReadEmitted(false) + readyReadPending(false), + inReadyRead(false) { - dataReadNotifier = new QWinOverlappedIoNotifier(this); - connect(dataReadNotifier, &QWinOverlappedIoNotifier::notified, this, &QWindowsPipeReader::notified); + connect(this, &QWindowsPipeReader::_q_queueReadyRead, + this, &QWindowsPipeReader::emitPendingReadyRead, Qt::QueuedConnection); } -static bool qt_cancelIo(HANDLE handle, OVERLAPPED *overlapped) +bool qt_cancelIo(HANDLE handle, OVERLAPPED *overlapped) { typedef BOOL (WINAPI *PtrCancelIoEx)(HANDLE, LPOVERLAPPED); static PtrCancelIoEx ptrCancelIoEx = 0; @@ -88,12 +100,6 @@ void QWindowsPipeReader::setHandle(HANDLE hPipeReadEnd) actualReadBufferSize = 0; handle = hPipeReadEnd; pipeBroken = false; - readyReadEmitted = false; - stopped = false; - if (hPipeReadEnd != INVALID_HANDLE_VALUE) { - dataReadNotifier->setHandle(hPipeReadEnd); - dataReadNotifier->setEnabled(true); - } } /*! @@ -104,19 +110,15 @@ void QWindowsPipeReader::stop() { stopped = true; if (readSequenceStarted) { - if (qt_cancelIo(handle, &overlapped)) { - dataReadNotifier->waitForNotified(-1, &overlapped); - } else { + if (!qt_cancelIo(handle, &overlapped)) { const DWORD dwError = GetLastError(); if (dwError != ERROR_NOT_FOUND) { qErrnoWarning(dwError, "QWindowsPipeReader: qt_cancelIo on handle %x failed.", handle); } } + waitForNotification(-1); } - readSequenceStarted = false; - dataReadNotifier->setEnabled(false); - handle = INVALID_HANDLE_VALUE; } /*! @@ -174,11 +176,10 @@ bool QWindowsPipeReader::canReadLine() const \internal Will be called whenever the read operation completes. */ -void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode, - OVERLAPPED *notifiedOverlapped) +void QWindowsPipeReader::notified(DWORD errorCode, DWORD numberOfBytesRead) { - if (&overlapped != notifiedOverlapped) - return; + notifiedCalled = true; + readSequenceStarted = false; switch (errorCode) { case ERROR_SUCCESS: @@ -202,8 +203,6 @@ void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode, break; } - readSequenceStarted = false; - // After the reader was stopped, the only reason why this function can be called is the // completion of a cancellation. No signals should be emitted, and no new read sequence should // be started in this case. @@ -218,13 +217,15 @@ void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode, actualReadBufferSize += numberOfBytesRead; readBuffer.truncate(actualReadBufferSize); startAsyncRead(); - readyReadEmitted = true; - emit readyRead(); + if (!readyReadPending) { + readyReadPending = true; + emit _q_queueReadyRead(QWindowsPipeReader::QPrivateSignal()); + } } /*! \internal - Reads data from the socket into the readbuffer + Reads data from the pipe into the readbuffer. */ void QWindowsPipeReader::startAsyncRead() { @@ -244,43 +245,41 @@ void QWindowsPipeReader::startAsyncRead() char *ptr = readBuffer.reserve(bytesToRead); + stopped = false; readSequenceStarted = true; - ZeroMemory(&overlapped, sizeof(overlapped)); - if (ReadFile(handle, ptr, bytesToRead, NULL, &overlapped)) { - // We get notified by the QWinOverlappedIoNotifier - even in the synchronous case. - return; - } else { + overlapped.clear(); + if (!ReadFileEx(handle, ptr, bytesToRead, &overlapped, &readFileCompleted)) { + readSequenceStarted = false; + const DWORD dwError = GetLastError(); switch (dwError) { - case ERROR_IO_PENDING: - // This is not an error. We're getting notified, when data arrives. - return; - case ERROR_MORE_DATA: - // This is not an error. The synchronous read succeeded. - // We're connected to a message mode pipe and the message - // didn't fit into the pipe's system buffer. - // We're getting notified by the QWinOverlappedIoNotifier. - break; case ERROR_BROKEN_PIPE: case ERROR_PIPE_NOT_CONNECTED: - { - // It may happen, that the other side closes the connection directly - // after writing data. Then we must set the appropriate socket state. - readSequenceStarted = false; - pipeBroken = true; - emit pipeClosed(); - return; - } + // It may happen, that the other side closes the connection directly + // after writing data. Then we must set the appropriate socket state. + pipeBroken = true; + emit pipeClosed(); + break; default: - readSequenceStarted = false; emit winError(dwError, QLatin1String("QWindowsPipeReader::startAsyncRead")); - return; + break; } } } /*! \internal + Called when ReadFileEx finished the read operation. + */ +void QWindowsPipeReader::readFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered, + OVERLAPPED *overlappedBase) +{ + Overlapped *overlapped = static_cast<Overlapped *>(overlappedBase); + overlapped->pipeReader->notified(errorCode, numberOfBytesTransfered); +} + +/*! + \internal Returns the number of available bytes in the pipe. Sets QWindowsPipeReader::pipeBroken to true if the connection is broken. */ @@ -298,17 +297,60 @@ DWORD QWindowsPipeReader::checkPipeState() return 0; } +bool QWindowsPipeReader::waitForNotification(int timeout) +{ + QElapsedTimer t; + t.start(); + notifiedCalled = false; + int msecs = timeout; + while (SleepEx(msecs == -1 ? INFINITE : msecs, TRUE) == WAIT_IO_COMPLETION) { + if (notifiedCalled) + return true; + + // Some other I/O completion routine was called. Wait some more. + msecs = qt_subtract_from_timeout(timeout, t.elapsed()); + if (!msecs) + break; + } + return notifiedCalled; +} + +void QWindowsPipeReader::emitPendingReadyRead() +{ + if (readyReadPending) { + readyReadPending = false; + inReadyRead = true; + emit readyRead(); + inReadyRead = false; + } +} + /*! Waits for the completion of the asynchronous read operation. - Returns \c true, if we've emitted the readyRead signal. + Returns \c true, if we've emitted the readyRead signal (non-recursive case) + or readyRead will be emitted by the event loop (recursive case). */ bool QWindowsPipeReader::waitForReadyRead(int msecs) { if (!readSequenceStarted) return false; - readyReadEmitted = false; - dataReadNotifier->waitForNotified(msecs, &overlapped); - return readyReadEmitted; + + if (readyReadPending) { + if (!inReadyRead) + emitPendingReadyRead(); + return true; + } + + if (!waitForNotification(msecs)) + return false; + + if (readyReadPending) { + if (!inReadyRead) + emitPendingReadyRead(); + return true; + } + + return false; } /*! diff --git a/src/corelib/io/qwindowspipereader_p.h b/src/corelib/io/qwindowspipereader_p.h index d389d0cc9f..74ff5250ac 100644 --- a/src/corelib/io/qwindowspipereader_p.h +++ b/src/corelib/io/qwindowspipereader_p.h @@ -51,7 +51,6 @@ // We mean it. // -#include <qbytearray.h> #include <qobject.h> #include <private/qringbuffer_p.h> @@ -59,9 +58,6 @@ QT_BEGIN_NAMESPACE - -class QWinOverlappedIoNotifier; - class Q_CORE_EXPORT QWindowsPipeReader : public QObject { Q_OBJECT @@ -70,6 +66,7 @@ public: ~QWindowsPipeReader(); void setHandle(HANDLE hPipeReadEnd); + void startAsyncRead(); void stop(); void setMaxReadBufferSize(qint64 size) { readBufferMaxSize = size; } @@ -82,31 +79,42 @@ public: bool waitForReadyRead(int msecs); bool waitForPipeClosed(int msecs); - void startAsyncRead(); bool isReadOperationActive() const { return readSequenceStarted; } Q_SIGNALS: void winError(ulong, const QString &); void readyRead(); void pipeClosed(); - -private Q_SLOTS: - void notified(quint32 numberOfBytesRead, quint32 errorCode, OVERLAPPED *notifiedOverlapped); + void _q_queueReadyRead(QPrivateSignal); private: + static void CALLBACK readFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered, + OVERLAPPED *overlappedBase); + void notified(DWORD errorCode, DWORD numberOfBytesRead); DWORD checkPipeState(); + bool waitForNotification(int timeout); + void emitPendingReadyRead(); + + class Overlapped : public OVERLAPPED + { + Q_DISABLE_COPY(Overlapped) + public: + explicit Overlapped(QWindowsPipeReader *reader); + void clear(); + QWindowsPipeReader *pipeReader; + }; -private: HANDLE handle; - OVERLAPPED overlapped; - QWinOverlappedIoNotifier *dataReadNotifier; + Overlapped overlapped; qint64 readBufferMaxSize; QRingBuffer readBuffer; qint64 actualReadBufferSize; bool stopped; bool readSequenceStarted; + bool notifiedCalled; bool pipeBroken; - bool readyReadEmitted; + bool readyReadPending; + bool inReadyRead; }; QT_END_NAMESPACE diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index c7144d2c6b..79e7d13eb5 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -38,144 +38,177 @@ ****************************************************************************/ #include "qwindowspipewriter_p.h" +#include "qiodevice_p.h" QT_BEGIN_NAMESPACE -#ifndef QT_NO_THREAD +extern bool qt_cancelIo(HANDLE handle, OVERLAPPED *overlapped); // from qwindowspipereader.cpp -QWindowsPipeWriter::QWindowsPipeWriter(HANDLE pipe, QObject * parent) - : QThread(parent), - writePipe(INVALID_HANDLE_VALUE), - quitNow(false), - hasWritten(false) + +QWindowsPipeWriter::Overlapped::Overlapped(QWindowsPipeWriter *pipeWriter) + : pipeWriter(pipeWriter) +{ +} + +void QWindowsPipeWriter::Overlapped::clear() { - DuplicateHandle(GetCurrentProcess(), pipe, GetCurrentProcess(), - &writePipe, 0, FALSE, DUPLICATE_SAME_ACCESS); + ZeroMemory(this, sizeof(OVERLAPPED)); +} + + +QWindowsPipeWriter::QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent) + : QObject(parent), + handle(pipeWriteEnd), + overlapped(this), + numberOfBytesToWrite(0), + pendingBytesWrittenValue(0), + stopped(true), + writeSequenceStarted(false), + notifiedCalled(false), + bytesWrittenPending(false), + inBytesWritten(false) +{ + connect(this, &QWindowsPipeWriter::_q_queueBytesWritten, + this, &QWindowsPipeWriter::emitPendingBytesWrittenValue, Qt::QueuedConnection); } QWindowsPipeWriter::~QWindowsPipeWriter() { - lock.lock(); - quitNow = true; - waitCondition.wakeOne(); - lock.unlock(); - if (!wait(30000)) - terminate(); - CloseHandle(writePipe); + stop(); } bool QWindowsPipeWriter::waitForWrite(int msecs) { - QMutexLocker locker(&lock); - bool hadWritten = hasWritten; - hasWritten = false; - if (hadWritten) + if (!writeSequenceStarted) + return false; + + if (bytesWrittenPending) { + if (!inBytesWritten) + emitPendingBytesWrittenValue(); return true; - if (!waitCondition.wait(&lock, msecs)) + } + + if (!waitForNotification(msecs)) return false; - hadWritten = hasWritten; - hasWritten = false; - return hadWritten; + + if (bytesWrittenPending) { + if (!inBytesWritten) + emitPendingBytesWrittenValue(); + return true; + } + + return false; } -qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen) +qint64 QWindowsPipeWriter::bytesToWrite() const { - if (!isRunning()) - return -1; - - QMutexLocker locker(&lock); - data.append(ptr, maxlen); - waitCondition.wakeOne(); - return maxlen; + return numberOfBytesToWrite; } -class QPipeWriterOverlapped +void QWindowsPipeWriter::emitPendingBytesWrittenValue() { -public: - QPipeWriterOverlapped() - { - overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (bytesWrittenPending) { + bytesWrittenPending = false; + const qint64 bytes = pendingBytesWrittenValue; + pendingBytesWrittenValue = 0; + + inBytesWritten = true; + emit bytesWritten(bytes); + inBytesWritten = false; + emit canWrite(); } +} - ~QPipeWriterOverlapped() - { - CloseHandle(overlapped.hEvent); - } +void QWindowsPipeWriter::writeFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered, + OVERLAPPED *overlappedBase) +{ + Overlapped *overlapped = static_cast<Overlapped *>(overlappedBase); + overlapped->pipeWriter->notified(errorCode, numberOfBytesTransfered); +} - void prepare() - { - const HANDLE hEvent = overlapped.hEvent; - ZeroMemory(&overlapped, sizeof overlapped); - overlapped.hEvent = hEvent; +/*! + \internal + Will be called whenever the write operation completes. + */ +void QWindowsPipeWriter::notified(DWORD errorCode, DWORD numberOfBytesWritten) +{ + notifiedCalled = true; + writeSequenceStarted = false; + numberOfBytesToWrite = 0; + + switch (errorCode) { + case ERROR_SUCCESS: + break; + case ERROR_OPERATION_ABORTED: + if (stopped) + break; + // fall through + default: + qErrnoWarning(errorCode, "QWindowsPipeWriter: asynchronous write failed."); + break; } - OVERLAPPED *operator&() - { - return &overlapped; + // After the writer was stopped, the only reason why this function can be called is the + // completion of a cancellation. No signals should be emitted, and no new write sequence should + // be started in this case. + if (stopped) + return; + + pendingBytesWrittenValue += qint64(numberOfBytesWritten); + if (!bytesWrittenPending) { + bytesWrittenPending = true; + emit _q_queueBytesWritten(QWindowsPipeWriter::QPrivateSignal()); } +} -private: - OVERLAPPED overlapped; -}; +bool QWindowsPipeWriter::waitForNotification(int timeout) +{ + QElapsedTimer t; + t.start(); + notifiedCalled = false; + int msecs = timeout; + while (SleepEx(msecs == -1 ? INFINITE : msecs, TRUE) == WAIT_IO_COMPLETION) { + if (notifiedCalled) + return true; + + // Some other I/O completion routine was called. Wait some more. + msecs = qt_subtract_from_timeout(timeout, t.elapsed()); + if (!msecs) + break; + } + return notifiedCalled; +} -void QWindowsPipeWriter::run() +qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen) { - QPipeWriterOverlapped overl; - forever { - lock.lock(); - while(data.isEmpty() && (!quitNow)) { - waitCondition.wakeOne(); - waitCondition.wait(&lock); - } + if (writeSequenceStarted) + return 0; + + overlapped.clear(); + numberOfBytesToWrite = maxlen; + stopped = false; + writeSequenceStarted = true; + if (!WriteFileEx(handle, ptr, maxlen, &overlapped, &writeFileCompleted)) { + writeSequenceStarted = false; + qErrnoWarning("QWindowsPipeWriter::write failed."); + } - if (quitNow) { - lock.unlock(); - quitNow = false; - break; - } + return maxlen; +} - QByteArray copy = data; - - lock.unlock(); - - const char *ptrData = copy.data(); - qint64 maxlen = copy.size(); - qint64 totalWritten = 0; - overl.prepare(); - while ((!quitNow) && totalWritten < maxlen) { - DWORD written = 0; - if (!WriteFile(writePipe, ptrData + totalWritten, - maxlen - totalWritten, &written, &overl)) { - const DWORD writeError = GetLastError(); - if (writeError == 0xE8/*NT_STATUS_INVALID_USER_BUFFER*/) { - // give the os a rest - msleep(100); - continue; - } - if (writeError != ERROR_IO_PENDING) { - qErrnoWarning(writeError, "QWindowsPipeWriter: async WriteFile failed."); - return; - } - if (!GetOverlappedResult(writePipe, &overl, &written, TRUE)) { - qErrnoWarning(GetLastError(), "QWindowsPipeWriter: GetOverlappedResult failed."); - return; - } +void QWindowsPipeWriter::stop() +{ + stopped = true; + if (writeSequenceStarted) { + if (!qt_cancelIo(handle, &overlapped)) { + const DWORD dwError = GetLastError(); + if (dwError != ERROR_NOT_FOUND) { + qErrnoWarning(dwError, "QWindowsPipeWriter: qt_cancelIo on handle %x failed.", + handle); } - totalWritten += written; -#if defined QPIPEWRITER_DEBUG - qDebug("QWindowsPipeWriter::run() wrote %d %d/%d bytes", - written, int(totalWritten), int(maxlen)); -#endif - lock.lock(); - data.remove(0, written); - hasWritten = true; - lock.unlock(); } - emit bytesWritten(totalWritten); - emit canWrite(); + waitForNotification(-1); } } -#endif //QT_NO_THREAD - QT_END_NAMESPACE diff --git a/src/corelib/io/qwindowspipewriter_p.h b/src/corelib/io/qwindowspipewriter_p.h index 49fb85ebdd..945cbd18bf 100644 --- a/src/corelib/io/qwindowspipewriter_p.h +++ b/src/corelib/io/qwindowspipewriter_p.h @@ -52,16 +52,11 @@ // #include <qelapsedtimer.h> -#include <qthread.h> -#include <qmutex.h> -#include <qwaitcondition.h> +#include <qobject.h> #include <qt_windows.h> QT_BEGIN_NAMESPACE - -#ifndef QT_NO_THREAD - #define SLEEPMIN 10 #define SLEEPMAX 500 @@ -110,45 +105,50 @@ private: int nextSleep; }; -class Q_CORE_EXPORT QWindowsPipeWriter : public QThread +class Q_CORE_EXPORT QWindowsPipeWriter : public QObject { Q_OBJECT - -Q_SIGNALS: - void canWrite(); - void bytesWritten(qint64 bytes); - public: - explicit QWindowsPipeWriter(HANDLE writePipe, QObject * parent = 0); + explicit QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent = 0); ~QWindowsPipeWriter(); - bool waitForWrite(int msecs); qint64 write(const char *data, qint64 maxlen); + void stop(); + bool waitForWrite(int msecs); + qint64 bytesToWrite() const; - qint64 bytesToWrite() const - { - QMutexLocker locker(&lock); - return data.size(); - } - - bool hadWritten() const - { - return hasWritten; - } - -protected: - void run(); +Q_SIGNALS: + void canWrite(); + void bytesWritten(qint64 bytes); + void _q_queueBytesWritten(QPrivateSignal); private: - QByteArray data; - QWaitCondition waitCondition; - mutable QMutex lock; - HANDLE writePipe; - volatile bool quitNow; - bool hasWritten; -}; + static void CALLBACK writeFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered, + OVERLAPPED *overlappedBase); + void notified(DWORD errorCode, DWORD numberOfBytesWritten); + bool waitForNotification(int timeout); + void emitPendingBytesWrittenValue(); -#endif //QT_NO_THREAD + class Overlapped : public OVERLAPPED + { + Q_DISABLE_COPY(Overlapped) + public: + explicit Overlapped(QWindowsPipeWriter *pipeWriter); + void clear(); + + QWindowsPipeWriter *pipeWriter; + }; + + HANDLE handle; + Overlapped overlapped; + qint64 numberOfBytesToWrite; + qint64 pendingBytesWrittenValue; + bool stopped; + bool writeSequenceStarted; + bool notifiedCalled; + bool bytesWrittenPending; + bool inBytesWritten; +}; QT_END_NAMESPACE diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp index bef105b184..a6f61afc90 100644 --- a/src/corelib/kernel/qeventdispatcher_winrt.cpp +++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp @@ -216,8 +216,10 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags) const QVector<HANDLE> timerHandles = d->timerIdToHandle.values().toVector(); if (waitTime) emit aboutToBlock(); + bool timerEventsSent = false; DWORD waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, waitTime, TRUE); - if (waitResult >= WAIT_OBJECT_0 && waitResult < WAIT_OBJECT_0 + timerHandles.count()) { + while (waitResult >= WAIT_OBJECT_0 && waitResult < WAIT_OBJECT_0 + timerHandles.count()) { + timerEventsSent = true; const HANDLE handle = timerHandles.value(waitResult - WAIT_OBJECT_0); ResetEvent(handle); const int timerId = d->timerHandleToId.value(handle); @@ -232,12 +234,10 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags) // Update timer's targetTime const quint64 targetTime = qt_msectime() + info.interval; info.targetTime = targetTime; - emit awake(); - return true; + waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, 0, TRUE); } emit awake(); - - if (userEventsSent) + if (timerEventsSent || userEventsSent) return true; // We cannot wait infinitely like on other platforms, as diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index a070ddd805..1f3d3dcfc7 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -119,8 +119,8 @@ public: Q_INVOKABLE explicit QObject(QObject *parent=Q_NULLPTR); virtual ~QObject(); - virtual bool event(QEvent *); - virtual bool eventFilter(QObject *, QEvent *); + virtual bool event(QEvent *event); + virtual bool eventFilter(QObject *watched, QEvent *event); #ifdef Q_QDOC static QString tr(const char *sourceText, const char *comment = Q_NULLPTR, int n = -1); @@ -195,9 +195,9 @@ public: inline const QObjectList &children() const { return d_ptr->children; } - void setParent(QObject *); - void installEventFilter(QObject *); - void removeEventFilter(QObject *); + void setParent(QObject *parent); + void installEventFilter(QObject *filterObj); + void removeEventFilter(QObject *obj); static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType = Qt::AutoConnection); @@ -428,9 +428,9 @@ protected: int receivers(const char* signal) const; bool isSignalConnected(const QMetaMethod &signal) const; - virtual void timerEvent(QTimerEvent *); - virtual void childEvent(QChildEvent *); - virtual void customEvent(QEvent *); + virtual void timerEvent(QTimerEvent *event); + virtual void childEvent(QChildEvent *event); + virtual void customEvent(QEvent *event); virtual void connectNotify(const QMetaMethod &signal); virtual void disconnectNotify(const QMetaMethod &signal); diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 48b94abae5..8a797772fc 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -310,8 +310,9 @@ QThreadPrivate::~QThreadPrivate() The effect of the \a priority parameter is dependent on the operating system's scheduling policy. In particular, the \a priority will be ignored on systems that do not support thread priorities - (such as on Linux, see http://linux.die.net/man/2/sched_setscheduler - for more details). + (such as on Linux, see the + \l {http://linux.die.net/man/2/sched_setscheduler}{sched_setscheduler} + documentation for more details). \sa run(), terminate() */ diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h index 31fdc8ce6b..b376b6b999 100644 --- a/src/corelib/tools/qrect.h +++ b/src/corelib/tools/qrect.h @@ -252,7 +252,7 @@ Q_DECL_CONSTEXPR inline QPoint QRect::bottomLeft() const Q_DECL_NOTHROW { return QPoint(x1, y2); } Q_DECL_CONSTEXPR inline QPoint QRect::center() const Q_DECL_NOTHROW -{ return QPoint((x1+x2)/2, (y1+y2)/2); } +{ return QPoint(int((qint64(x1)+x2)/2), int((qint64(y1)+y2)/2)); } // cast avoids overflow on addition Q_DECL_CONSTEXPR inline int QRect::width() const Q_DECL_NOTHROW { return x2 - x1 + 1; } diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp index 4672248945..3c7417d64e 100644 --- a/src/corelib/tools/qtimezone.cpp +++ b/src/corelib/tools/qtimezone.cpp @@ -67,7 +67,7 @@ static QTimeZonePrivate *newBackendTimeZone() #elif defined Q_OS_UNIX return new QTzTimeZonePrivate(); // Registry based timezone backend not available on WinRT -#elif defined Q_OS_WIN && !defined Q_OS_WINRT +#elif defined Q_OS_WIN return new QWinTimeZonePrivate(); #elif defined QT_USE_ICU return new QIcuTimeZonePrivate(); @@ -94,7 +94,7 @@ static QTimeZonePrivate *newBackendTimeZone(const QByteArray &ianaId) #elif defined Q_OS_UNIX return new QTzTimeZonePrivate(ianaId); // Registry based timezone backend not available on WinRT -#elif defined Q_OS_WIN && !defined Q_OS_WINRT +#elif defined Q_OS_WIN return new QWinTimeZonePrivate(ianaId); #elif defined QT_USE_ICU return new QIcuTimeZonePrivate(ianaId); diff --git a/src/corelib/tools/qtimezoneprivate_win.cpp b/src/corelib/tools/qtimezoneprivate_win.cpp index 1d19f01b4e..f84b66fa99 100644 --- a/src/corelib/tools/qtimezoneprivate_win.cpp +++ b/src/corelib/tools/qtimezoneprivate_win.cpp @@ -48,6 +48,10 @@ QT_BEGIN_NAMESPACE +#ifndef Q_OS_WINRT +#define QT_USE_REGISTRY_TIMEZONE 1 +#endif + /* Private @@ -65,9 +69,10 @@ QT_BEGIN_NAMESPACE // Vista introduced support for historic data, see MSDN docs on DYNAMIC_TIME_ZONE_INFORMATION // http://msdn.microsoft.com/en-gb/library/windows/desktop/ms724253%28v=vs.85%29.aspx - +#ifdef QT_USE_REGISTRY_TIMEZONE static const char tzRegPath[] = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones"; static const char currTzRegPath[] = "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation"; +#endif enum { MIN_YEAR = -292275056, @@ -129,6 +134,7 @@ static bool equalTzi(const TIME_ZONE_INFORMATION &tzi1, const TIME_ZONE_INFORMAT && wcscmp(tzi1.DaylightName, tzi2.DaylightName) == 0); } +#ifdef QT_USE_REGISTRY_TIMEZONE static bool openRegistryKey(const QString &keyPath, HKEY *key) { return (RegOpenKeyEx(HKEY_LOCAL_MACHINE, (const wchar_t*)keyPath.utf16(), 0, KEY_READ, key) @@ -203,9 +209,61 @@ static TIME_ZONE_INFORMATION getRegistryTzi(const QByteArray &windowsId, bool *o return tzi; } +#else // QT_USE_REGISTRY_TIMEZONE +struct QWinDynamicTimeZone +{ + QString standardName; + QString daylightName; + QString timezoneName; + qint32 bias; + bool daylightTime; +}; + +typedef QHash<QByteArray, QWinDynamicTimeZone> QWinRTTimeZoneHash; + +Q_GLOBAL_STATIC(QWinRTTimeZoneHash, gTimeZones) + +static void enumerateTimeZones() +{ + DYNAMIC_TIME_ZONE_INFORMATION dtzInfo; + quint32 index = 0; + QString prevTimeZoneKeyName; + while (SUCCEEDED(EnumDynamicTimeZoneInformation(index++, &dtzInfo))) { + QWinDynamicTimeZone item; + item.timezoneName = QString::fromWCharArray(dtzInfo.TimeZoneKeyName); + // As soon as key name repeats, break. Some systems continue to always + // return the last item independent of index being out of range + if (item.timezoneName == prevTimeZoneKeyName) + break; + item.standardName = QString::fromWCharArray(dtzInfo.StandardName); + item.daylightName = QString::fromWCharArray(dtzInfo.DaylightName); + item.daylightTime = !dtzInfo.DynamicDaylightTimeDisabled; + item.bias = dtzInfo.Bias; + gTimeZones->insert(item.timezoneName.toUtf8(), item); + prevTimeZoneKeyName = item.timezoneName; + } +} + +static DYNAMIC_TIME_ZONE_INFORMATION dynamicInfoForId(const QByteArray &windowsId) +{ + DYNAMIC_TIME_ZONE_INFORMATION dtzInfo; + quint32 index = 0; + QString prevTimeZoneKeyName; + while (SUCCEEDED(EnumDynamicTimeZoneInformation(index++, &dtzInfo))) { + const QString timeZoneName = QString::fromWCharArray(dtzInfo.TimeZoneKeyName); + if (timeZoneName == QLatin1String(windowsId)) + break; + if (timeZoneName == prevTimeZoneKeyName) + break; + prevTimeZoneKeyName = timeZoneName; + } + return dtzInfo; +} +#endif // QT_USE_REGISTRY_TIMEZONE static QList<QByteArray> availableWindowsIds() { +#ifdef QT_USE_REGISTRY_TIMEZONE // TODO Consider caching results in a global static, very unlikely to change. QList<QByteArray> list; HKEY key = NULL; @@ -223,10 +281,16 @@ static QList<QByteArray> availableWindowsIds() RegCloseKey(key); } return list; +#else // QT_USE_REGISTRY_TIMEZONE + if (gTimeZones->isEmpty()) + enumerateTimeZones(); + return gTimeZones->keys(); +#endif // QT_USE_REGISTRY_TIMEZONE } static QByteArray windowsSystemZoneId() { +#ifdef QT_USE_REGISTRY_TIMEZONE // On Vista and later is held in the value TimeZoneKeyName in key currTzRegPath QString id; HKEY key = NULL; @@ -248,6 +312,11 @@ static QByteArray windowsSystemZoneId() if (equalTzi(getRegistryTzi(winId, &ok), sysTzi)) return winId; } +#else // QT_USE_REGISTRY_TIMEZONE + DYNAMIC_TIME_ZONE_INFORMATION dtzi; + if (SUCCEEDED(GetDynamicTimeZoneInformation(&dtzi))) + return QString::fromWCharArray(dtzi.TimeZoneKeyName).toLocal8Bit(); +#endif // QT_USE_REGISTRY_TIMEZONE // If we can't determine the current ID use UTC return QTimeZonePrivate::utcQByteArray(); @@ -368,6 +437,7 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId) } if (!m_windowsId.isEmpty()) { +#ifdef QT_USE_REGISTRY_TIMEZONE // Open the base TZI for the time zone HKEY baseKey = NULL; const QString baseKeyPath = QString::fromUtf8(tzRegPath) + QLatin1Char('\\') @@ -404,6 +474,34 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId) } RegCloseKey(baseKey); } +#else // QT_USE_REGISTRY_TIMEZONE + if (gTimeZones->isEmpty()) + enumerateTimeZones(); + QWinRTTimeZoneHash::const_iterator it = gTimeZones->find(m_windowsId); + if (it != gTimeZones->constEnd()) { + m_displayName = it->timezoneName; + m_standardName = it->standardName; + m_daylightName = it->daylightName; + DWORD firstYear = 0; + DWORD lastYear = 0; + DYNAMIC_TIME_ZONE_INFORMATION dtzi = dynamicInfoForId(m_windowsId); + GetDynamicTimeZoneInformationEffectiveYears(&dtzi, &firstYear, &lastYear); + // If there is no dynamic information, you can still query for + // year 0, which helps simplifying following part + for (DWORD year = firstYear; year <= lastYear; ++year) { + TIME_ZONE_INFORMATION tzi; + if (!GetTimeZoneInformationForYear(year, &dtzi, &tzi)) + continue; + QWinTransitionRule rule; + rule.standardTimeBias = tzi.Bias + tzi.StandardBias; + rule.daylightTimeBias = tzi.Bias + tzi.DaylightBias - rule.standardTimeBias; + rule.standardTimeRule = tzi.StandardDate; + rule.daylightTimeRule = tzi.DaylightDate; + rule.startYear = year; + m_tranRules.append(rule); + } + } +#endif // QT_USE_REGISTRY_TIMEZONE } // If there are no rules then we failed to find a windowsId or any tzi info diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index e367e6e716..93dc71c3d8 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -144,9 +144,11 @@ else:unix { SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp tools/qtimezoneprivate_tz.cpp } else:win32 { - SOURCES += tools/qelapsedtimer_win.cpp tools/qlocale_win.cpp - !winrt: SOURCES += tools/qtimezoneprivate_win.cpp + SOURCES += tools/qelapsedtimer_win.cpp \ + tools/qlocale_win.cpp \ + tools/qtimezoneprivate_win.cpp winphone: LIBS_PRIVATE += -lWindowsPhoneGlobalizationUtil + winrt-*-msvc2013: LIBS += advapi32.lib } else:integrity:SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp else:SOURCES += tools/qelapsedtimer_generic.cpp diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 94b91865ab..105714ee64 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -487,6 +487,11 @@ QDBusSpyCallEvent::~QDBusSpyCallEvent() void QDBusSpyCallEvent::placeMetaCall(QObject *) { + invokeSpyHooks(msg, hooks, hookCount); +} + +inline void QDBusSpyCallEvent::invokeSpyHooks(const QDBusMessage &msg, const Hook *hooks, int hookCount) +{ // call the spy hook list for (int i = 0; i < hookCount; ++i) hooks[i](msg); @@ -515,7 +520,12 @@ bool QDBusConnectionPrivate::handleMessage(const QDBusMessage &amsg) { if (!ref.load()) return false; - if (!dispatchEnabled && !QDBusMessagePrivate::isLocal(amsg)) { + + // local message are always delivered, regardless of filtering + // or whether the dispatcher is enabled + bool isLocal = QDBusMessagePrivate::isLocal(amsg); + + if (!dispatchEnabled && !isLocal) { // queue messages only, we'll handle them later qDBusDebug() << this << "delivery is suspended"; pendingMessages << amsg; @@ -529,13 +539,23 @@ bool QDBusConnectionPrivate::handleMessage(const QDBusMessage &amsg) // let them see the signal too return false; case QDBusMessage::MethodCallMessage: - // run it through the spy filters (if any) before the regular processing + // run it through the spy filters (if any) before the regular processing: + // a) if it's a local message, we're in the caller's thread, so invoke the filter directly + // b) if it's an external message, post to the main thread if (Q_UNLIKELY(qDBusSpyHookList.exists()) && qApp) { const QDBusSpyHookList &list = *qDBusSpyHookList; - qDBusDebug() << this << "invoking message spies"; - QCoreApplication::postEvent(qApp, new QDBusSpyCallEvent(this, QDBusConnection(this), - amsg, list.constData(), list.size())); - return true; + if (isLocal) { + Q_ASSERT(QThread::currentThread() != thread()); + qDBusDebug() << this << "invoking message spies directly"; + QDBusSpyCallEvent::invokeSpyHooks(amsg, list.constData(), list.size()); + } else { + qDBusDebug() << this << "invoking message spies via event"; + QCoreApplication::postEvent(qApp, new QDBusSpyCallEvent(this, QDBusConnection(this), + amsg, list.constData(), list.size())); + + // we'll be called back, so return + return true; + } } handleObjectCall(amsg); @@ -1456,9 +1476,9 @@ void QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg) // that means the dispatchLock mutex is locked // must not call out to user code in that case // - // however, if the message is internal, handleMessage was called - // directly and no lock is in place. We can therefore call out to - // user code, if necessary + // however, if the message is internal, handleMessage was called directly + // (user's thread) and no lock is in place. We can therefore call out to + // user code, if necessary. ObjectTreeNode result; int usedLength; QThread *objThread = 0; @@ -1497,12 +1517,14 @@ void QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg) usedLength, msg)); return; } else if (objThread != QThread::currentThread()) { - // synchronize with other thread + // looped-back message, targeting another thread: + // synchronize with it postEventToThread(HandleObjectCallPostEventAction, result.obj, new QDBusActivateObjectEvent(QDBusConnection(this), this, result, usedLength, msg, &sem)); semWait = true; } else { + // looped-back message, targeting current thread semWait = false; } } // release the lock diff --git a/src/dbus/qdbusintegrator_p.h b/src/dbus/qdbusintegrator_p.h index 89043148e3..470baeb692 100644 --- a/src/dbus/qdbusintegrator_p.h +++ b/src/dbus/qdbusintegrator_p.h @@ -151,6 +151,7 @@ public: {} ~QDBusSpyCallEvent(); void placeMetaCall(QObject *) Q_DECL_OVERRIDE; + static inline void invokeSpyHooks(const QDBusMessage &msg, const Hook *hooks, int hookCount); QDBusConnection conn; // keeps the refcount in QDBusConnectionPrivate up QDBusMessage msg; diff --git a/src/gui/kernel/qshapedpixmapdndwindow.cpp b/src/gui/kernel/qshapedpixmapdndwindow.cpp index 2cfbc4caa4..40bf15b807 100644 --- a/src/gui/kernel/qshapedpixmapdndwindow.cpp +++ b/src/gui/kernel/qshapedpixmapdndwindow.cpp @@ -48,52 +48,31 @@ QT_BEGIN_NAMESPACE QShapedPixmapWindow::QShapedPixmapWindow(QScreen *screen) - : QWindow(screen), - m_backingStore(0), - m_useCompositing(true) + : m_useCompositing(true) { + setScreen(screen); QSurfaceFormat format; format.setAlphaBufferSize(8); setFormat(format); - setSurfaceType(RasterSurface); - setFlags(Qt::ToolTip | Qt::FramelessWindowHint | - Qt::X11BypassWindowManagerHint | Qt::WindowTransparentForInput | Qt::WindowDoesNotAcceptFocus); - create(); - m_backingStore = new QBackingStore(this); + setFlags(Qt::ToolTip | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint + | Qt::WindowTransparentForInput | Qt::WindowDoesNotAcceptFocus); } QShapedPixmapWindow::~QShapedPixmapWindow() { - delete m_backingStore; - m_backingStore = 0; -} - -void QShapedPixmapWindow::render() -{ - QRect rect(QPoint(), geometry().size()); - - m_backingStore->beginPaint(rect); - - QPaintDevice *device = m_backingStore->paintDevice(); - - { - QPainter p(device); - if (m_useCompositing) - p.setCompositionMode(QPainter::CompositionMode_Source); - else - p.fillRect(rect, QGuiApplication::palette().base()); - p.drawPixmap(0, 0, m_pixmap); - } - - m_backingStore->endPaint(); - m_backingStore->flush(rect); } void QShapedPixmapWindow::setPixmap(const QPixmap &pixmap) { m_pixmap = pixmap; - if (!m_useCompositing) - setMask(m_pixmap.mask()); + if (!m_useCompositing) { + const QBitmap mask = m_pixmap.mask(); + if (!mask.isNull()) { + if (!handle()) + create(); + setMask(mask); + } + } } void QShapedPixmapWindow::setHotspot(const QPoint &hotspot) @@ -101,19 +80,28 @@ void QShapedPixmapWindow::setHotspot(const QPoint &hotspot) m_hotSpot = hotspot; } -void QShapedPixmapWindow::updateGeometry(const QPoint &pos) +void QShapedPixmapWindow::paintEvent(QPaintEvent *) { - if (m_pixmap.isNull()) - m_backingStore->resize(QSize(1,1)); - else if (m_backingStore->size() != m_pixmap.size()) - m_backingStore->resize(m_pixmap.size()); - - setGeometry(QRect(pos - m_hotSpot, m_backingStore->size())); + if (!m_pixmap.isNull()) { + const QRect rect(QPoint(0, 0), size()); + QPainter painter(this); + if (m_useCompositing) + painter.setCompositionMode(QPainter::CompositionMode_Source); + else + painter.fillRect(rect, QGuiApplication::palette().base()); + painter.drawPixmap(rect, m_pixmap); + } } -void QShapedPixmapWindow::exposeEvent(QExposeEvent *) +void QShapedPixmapWindow::updateGeometry(const QPoint &pos) { - render(); + QSize size(1, 1); + if (!m_pixmap.isNull()) { + size = qFuzzyCompare(m_pixmap.devicePixelRatio(), 1.0) + ? m_pixmap.size() + : (QSizeF(m_pixmap.size()) / m_pixmap.devicePixelRatio()).toSize(); + } + setGeometry(QRect(pos - m_hotSpot, size)); } QT_END_NAMESPACE diff --git a/src/gui/kernel/qshapedpixmapdndwindow_p.h b/src/gui/kernel/qshapedpixmapdndwindow_p.h index 65a4e3cfa7..21cecba9e8 100644 --- a/src/gui/kernel/qshapedpixmapdndwindow_p.h +++ b/src/gui/kernel/qshapedpixmapdndwindow_p.h @@ -51,21 +51,18 @@ // We mean it. // -#include <QtGui/QWindow> +#include <QtGui/QRasterWindow> #include <QtGui/QPixmap> -#include <QtGui/QBackingStore> QT_BEGIN_NAMESPACE -class QShapedPixmapWindow : public QWindow +class QShapedPixmapWindow : public QRasterWindow { Q_OBJECT public: explicit QShapedPixmapWindow(QScreen *screen = 0); ~QShapedPixmapWindow(); - void render(); - void setUseCompositing(bool on) { m_useCompositing = on; } void setPixmap(const QPixmap &pixmap); void setHotspot(const QPoint &hotspot); @@ -73,10 +70,9 @@ public: void updateGeometry(const QPoint &pos); protected: - void exposeEvent(QExposeEvent *) Q_DECL_OVERRIDE; + void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE; private: - QBackingStore *m_backingStore; QPixmap m_pixmap; QPoint m_hotSpot; bool m_useCompositing; diff --git a/src/gui/painting/qcosmeticstroker.cpp b/src/gui/painting/qcosmeticstroker.cpp index ba0d1871d1..4965762d74 100644 --- a/src/gui/painting/qcosmeticstroker.cpp +++ b/src/gui/painting/qcosmeticstroker.cpp @@ -68,8 +68,8 @@ static inline uint sourceOver(uint d, uint color) inline static int F16Dot16FixedDiv(int x, int y) { if (qAbs(x) > 0x7fff) - return (((qlonglong)x) << 16) / y; - return (x << 16) / y; + return qlonglong(x) * (1<<16) / y; + return x * (1<<16) / y; } typedef void (*DrawPixel)(QCosmeticStroker *stroker, int x, int y, int coverage); @@ -441,14 +441,14 @@ void QCosmeticStroker::calculateLastPoint(qreal rx1, qreal ry1, qreal rx2, qreal qSwap(x1, x2); } int xinc = F16Dot16FixedDiv(x2 - x1, y2 - y1); - int x = x1 << 10; + int x = x1 * (1<<10); int y = (y1 + 32) >> 6; int ys = (y2 + 32) >> 6; int round = (xinc > 0) ? 32 : 0; if (y != ys) { - x += ( ((((y << 6) + round - y1))) * xinc ) >> 6; + x += ((y * (1<<6)) + round - y1) * xinc >> 6; if (swapped) { lastPixel.x = x >> 16; @@ -480,7 +480,7 @@ void QCosmeticStroker::calculateLastPoint(qreal rx1, qreal ry1, qreal rx2, qreal int round = (yinc > 0) ? 32 : 0; if (x != xs) { - y += ( ((((x << 6) + round - x1))) * yinc ) >> 6; + y += ((x * (1<<6)) + round - x1) * yinc >> 6; if (swapped) { lastPixel.x = x; @@ -759,7 +759,7 @@ static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, dir = QCosmeticStroker::BottomToTop; } int xinc = F16Dot16FixedDiv(x2 - x1, y2 - y1); - int x = x1 << 10; + int x = x1 * (1<<10); if ((stroker->lastDir ^ QCosmeticStroker::VerticalMask) == dir) caps |= swapped ? QCosmeticStroker::CapEnd : QCosmeticStroker::CapBegin; @@ -771,7 +771,7 @@ static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, int round = (xinc > 0) ? 32 : 0; if (y != ys) { - x += ( ((((y << 6) + round - y1))) * xinc ) >> 6; + x += ((y * (1<<6)) + round - y1) * xinc >> 6; // calculate first and last pixel and perform dropout control QCosmeticStroker::Point first; @@ -810,7 +810,7 @@ static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, stroker->lastDir = dir; stroker->lastAxisAligned = axisAligned; - Dasher dasher(stroker, swapped, y << 6, ys << 6); + Dasher dasher(stroker, swapped, y * (1<<6), ys * (1<<6)); do { if (dasher.on()) @@ -836,7 +836,7 @@ static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, dir = QCosmeticStroker::RightToLeft; } int yinc = F16Dot16FixedDiv(y2 - y1, x2 - x1); - int y = y1 << 10; + int y = y1 * (1<<10); if ((stroker->lastDir ^ QCosmeticStroker::HorizontalMask) == dir) caps |= swapped ? QCosmeticStroker::CapEnd : QCosmeticStroker::CapBegin; @@ -848,7 +848,7 @@ static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, int round = (yinc > 0) ? 32 : 0; if (x != xs) { - y += ( ((((x << 6) + round - x1))) * yinc ) >> 6; + y += ((x * (1<<6)) + round - x1) * yinc >> 6; // calculate first and last pixel to perform dropout control QCosmeticStroker::Point first; @@ -886,7 +886,7 @@ static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, stroker->lastDir = dir; stroker->lastAxisAligned = axisAligned; - Dasher dasher(stroker, swapped, x << 6, xs << 6); + Dasher dasher(stroker, swapped, x * (1<<6), xs * (1<<6)); do { if (dasher.on()) @@ -929,7 +929,7 @@ static bool drawLineAA(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx caps = swapCaps(caps); } - int x = (x1 - 32) << 10; + int x = (x1 - 32) * (1<<10); x -= ( ((y1 & 63) - 32) * xinc ) >> 6; capAdjust(caps, y1, y2, x, xinc); @@ -992,7 +992,7 @@ static bool drawLineAA(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx caps = swapCaps(caps); } - int y = (y1 - 32) << 10; + int y = (y1 - 32) * (1<<10); y -= ( ((x1 & 63) - 32) * yinc ) >> 6; capAdjust(caps, x1, x2, y, yinc); diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 898b268070..7e18250087 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -137,7 +137,7 @@ extern bool qt_is_gui_used; Q_GUI_EXPORT int qt_defaultDpiX() { - if (qApp->testAttribute(Qt::AA_Use96Dpi)) + if (QCoreApplication::instance()->testAttribute(Qt::AA_Use96Dpi)) return 96; if (!qt_is_gui_used) @@ -152,7 +152,7 @@ Q_GUI_EXPORT int qt_defaultDpiX() Q_GUI_EXPORT int qt_defaultDpiY() { - if (qApp->testAttribute(Qt::AA_Use96Dpi)) + if (QCoreApplication::instance()->testAttribute(Qt::AA_Use96Dpi)) return 96; if (!qt_is_gui_used) diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp index ca6093227d..6065e17d9b 100644 --- a/src/gui/text/qrawfont.cpp +++ b/src/gui/text/qrawfont.cpp @@ -614,8 +614,7 @@ QByteArray QRawFont::fontTable(const char *tagName) const if (!d->isValid()) return QByteArray(); - const quint32 *tagId = reinterpret_cast<const quint32 *>(tagName); - return d->fontEngine->getSfntTable(qToBigEndian(*tagId)); + return d->fontEngine->getSfntTable(MAKE_TAG(tagName[0], tagName[1], tagName[2], tagName[3])); } /*! diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index 43eb85f1af..3adf71ccfb 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -128,7 +128,7 @@ static QByteArray makeCacheKey(QUrl &url, QNetworkProxy *proxy) { QString result; QUrl copy = url; - QString scheme = copy.scheme().toLower(); + QString scheme = copy.scheme(); bool isEncrypted = scheme == QLatin1String("https"); copy.setPort(copy.port(isEncrypted ? 443 : 80)); if (scheme == QLatin1String("preconnect-http")) { diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 995643a15a..d2b1a8a912 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1125,42 +1125,40 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera Q_D(QNetworkAccessManager); bool isLocalFile = req.url().isLocalFile(); - QString scheme = req.url().scheme().toLower(); + QString scheme = req.url().scheme(); // fast path for GET on file:// URLs // The QNetworkAccessFileBackend will right now only be used for PUT - if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation) - && (isLocalFile || scheme == QLatin1String("qrc") -#if defined(Q_OS_ANDROID) + if (op == QNetworkAccessManager::GetOperation + || op == QNetworkAccessManager::HeadOperation) { + if (isLocalFile +#ifdef Q_OS_ANDROID || scheme == QLatin1String("assets") #endif - )) { - return new QNetworkReplyFileImpl(this, req, op); - } + || scheme == QLatin1String("qrc")) { + return new QNetworkReplyFileImpl(this, req, op); + } - if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation) - && scheme == QLatin1String("data")) { - return new QNetworkReplyDataImpl(this, req, op); - } + if (scheme == QLatin1String("data")) + return new QNetworkReplyDataImpl(this, req, op); - // A request with QNetworkRequest::AlwaysCache does not need any bearer management - QNetworkRequest::CacheLoadControl mode = - static_cast<QNetworkRequest::CacheLoadControl>( - req.attribute(QNetworkRequest::CacheLoadControlAttribute, + // A request with QNetworkRequest::AlwaysCache does not need any bearer management + QNetworkRequest::CacheLoadControl mode = + static_cast<QNetworkRequest::CacheLoadControl>( + req.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt()); - if (mode == QNetworkRequest::AlwaysCache - && (op == QNetworkAccessManager::GetOperation - || op == QNetworkAccessManager::HeadOperation)) { - // FIXME Implement a QNetworkReplyCacheImpl instead, see QTBUG-15106 - QNetworkReplyImpl *reply = new QNetworkReplyImpl(this); - QNetworkReplyImplPrivate *priv = reply->d_func(); - priv->manager = this; - priv->backend = new QNetworkAccessCacheBackend(); - priv->backend->manager = this->d_func(); - priv->backend->setParent(reply); - priv->backend->reply = priv; - priv->setup(op, req, outgoingData); - return reply; + if (mode == QNetworkRequest::AlwaysCache) { + // FIXME Implement a QNetworkReplyCacheImpl instead, see QTBUG-15106 + QNetworkReplyImpl *reply = new QNetworkReplyImpl(this); + QNetworkReplyImplPrivate *priv = reply->d_func(); + priv->manager = this; + priv->backend = new QNetworkAccessCacheBackend(); + priv->backend->manager = this->d_func(); + priv->backend->setParent(reply); + priv->backend->reply = priv; + priv->setup(op, req, outgoingData); + return reply; + } } #ifndef QT_NO_BEARERMANAGEMENT diff --git a/src/network/access/qnetworkcookiejar.cpp b/src/network/access/qnetworkcookiejar.cpp index 412b8d859d..398895e92f 100644 --- a/src/network/access/qnetworkcookiejar.cpp +++ b/src/network/access/qnetworkcookiejar.cpp @@ -224,7 +224,7 @@ QList<QNetworkCookie> QNetworkCookieJar::cookiesForUrl(const QUrl &url) const Q_D(const QNetworkCookieJar); const QDateTime now = QDateTime::currentDateTimeUtc(); QList<QNetworkCookie> result; - bool isEncrypted = url.scheme().toLower() == QLatin1String("https"); + bool isEncrypted = url.scheme() == QLatin1String("https"); // scan our cookies for something that matches QList<QNetworkCookie>::ConstIterator it = d->allCookies.constBegin(), diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index aed05575e3..e1323527f6 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -634,7 +634,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq httpRequest.setUrl(url); httpRequest.setRedirectCount(newHttpRequest.maximumRedirectsAllowed()); - QString scheme = url.scheme().toLower(); + QString scheme = url.scheme(); bool ssl = (scheme == QLatin1String("https") || scheme == QLatin1String("preconnect-https")); q->setAttribute(QNetworkRequest::ConnectionEncryptedAttribute, ssl); diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index c188918024..f674cd5c2e 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -806,10 +806,10 @@ static QByteArray headerValue(QNetworkRequest::KnownHeaders header, const QVaria return QByteArray(); } -static QNetworkRequest::KnownHeaders parseHeaderName(const QByteArray &headerName) +static int parseHeaderName(const QByteArray &headerName) { if (headerName.isEmpty()) - return QNetworkRequest::KnownHeaders(-1); + return -1; switch (tolower(headerName.at(0))) { case 'c': @@ -841,7 +841,7 @@ static QNetworkRequest::KnownHeaders parseHeaderName(const QByteArray &headerNam break; } - return QNetworkRequest::KnownHeaders(-1); // nothing found + return -1; // nothing found } static QVariant parseHttpDate(const QByteArray &raw) @@ -1012,8 +1012,10 @@ void QNetworkHeadersPrivate::setRawHeaderInternal(const QByteArray &key, const Q void QNetworkHeadersPrivate::parseAndSetHeader(const QByteArray &key, const QByteArray &value) { // is it a known header? - QNetworkRequest::KnownHeaders parsedKey = parseHeaderName(key); - if (parsedKey != QNetworkRequest::KnownHeaders(-1)) { + const int parsedKeyAsInt = parseHeaderName(key); + if (parsedKeyAsInt != -1) { + const QNetworkRequest::KnownHeaders parsedKey + = static_cast<QNetworkRequest::KnownHeaders>(parsedKeyAsInt); if (value.isNull()) { cookedHeaders.remove(parsedKey); } else if (parsedKey == QNetworkRequest::ContentLengthHeader diff --git a/src/network/socket/qlocalserver_win.cpp b/src/network/socket/qlocalserver_win.cpp index dae1f82063..8cb3449343 100644 --- a/src/network/socket/qlocalserver_win.cpp +++ b/src/network/socket/qlocalserver_win.cpp @@ -198,6 +198,9 @@ bool QLocalServerPrivate::addListener() memset(&listener.overlapped, 0, sizeof(listener.overlapped)); listener.overlapped.hEvent = eventHandle; + + // Beware! ConnectNamedPipe will reset the eventHandle to non-signaled. + // Callers of addListener must check all listeners for connections. if (!ConnectNamedPipe(listener.handle, &listener.overlapped)) { switch (GetLastError()) { case ERROR_IO_PENDING: @@ -205,7 +208,6 @@ bool QLocalServerPrivate::addListener() break; case ERROR_PIPE_CONNECTED: listener.connected = true; - SetEvent(eventHandle); break; default: CloseHandle(listener.handle); @@ -257,6 +259,8 @@ bool QLocalServerPrivate::listen(const QString &name) for (int i = 0; i < SYSTEM_MAX_PENDING_SOCKETS; ++i) if (!addListener()) return false; + + _q_onNewConnection(); return true; } @@ -270,37 +274,43 @@ void QLocalServerPrivate::_q_onNewConnection() { Q_Q(QLocalServer); DWORD dummy; - - // Reset first, otherwise we could reset an event which was asserted - // immediately after we checked the conn status. - ResetEvent(eventHandle); - - // Testing shows that there is indeed absolutely no guarantee which listener gets - // a client connection first, so there is no way around polling all of them. - for (int i = 0; i < listeners.size(); ) { - HANDLE handle = listeners[i].handle; - if (listeners[i].connected - || GetOverlappedResult(handle, &listeners[i].overlapped, &dummy, FALSE)) - { - listeners.removeAt(i); - - addListener(); - - if (pendingConnections.size() > maxPendingConnections) - connectionEventNotifier->setEnabled(false); - - // Make this the last thing so connected slots can wreak the least havoc - q->incomingConnection((quintptr)handle); - } else { - if (GetLastError() != ERROR_IO_INCOMPLETE) { - q->close(); - setError(QLatin1String("QLocalServerPrivate::_q_onNewConnection")); - return; + bool tryAgain; + do { + tryAgain = false; + + // Reset first, otherwise we could reset an event which was asserted + // immediately after we checked the conn status. + ResetEvent(eventHandle); + + // Testing shows that there is indeed absolutely no guarantee which listener gets + // a client connection first, so there is no way around polling all of them. + for (int i = 0; i < listeners.size(); ) { + HANDLE handle = listeners[i].handle; + if (listeners[i].connected + || GetOverlappedResult(handle, &listeners[i].overlapped, &dummy, FALSE)) + { + listeners.removeAt(i); + + addListener(); + + if (pendingConnections.size() > maxPendingConnections) + connectionEventNotifier->setEnabled(false); + else + tryAgain = true; + + // Make this the last thing so connected slots can wreak the least havoc + q->incomingConnection((quintptr)handle); + } else { + if (GetLastError() != ERROR_IO_INCOMPLETE) { + q->close(); + setError(QLatin1String("QLocalServerPrivate::_q_onNewConnection")); + return; + } + + ++i; } - - ++i; } - } + } while (tryAgain); } void QLocalServerPrivate::closeServer() diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp index 70a738864b..7f9b8a7b06 100644 --- a/src/network/socket/qlocalsocket_win.cpp +++ b/src/network/socket/qlocalsocket_win.cpp @@ -220,7 +220,6 @@ qint64 QLocalSocket::writeData(const char *data, qint64 maxSize) d->pipeWriter = new QWindowsPipeWriter(d->handle, this); connect(d->pipeWriter, SIGNAL(canWrite()), this, SLOT(_q_canWrite())); connect(d->pipeWriter, SIGNAL(bytesWritten(qint64)), this, SIGNAL(bytesWritten(qint64))); - d->pipeWriter->start(); } return d->pipeWriter->write(data, maxSize); } diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index fcc267e7cc..b86b69cad4 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -399,6 +399,10 @@ bool QSslSocketBackendPrivate::initSslContext() if (!ace.isEmpty() && !QHostAddress().setAddress(tlsHostName) && !(configuration.sslOptions & QSsl::SslOptionDisableServerNameIndication)) { + // We don't send the trailing dot from the host header if present see + // https://tools.ietf.org/html/rfc6066#section-3 + if (ace.endsWith('.')) + ace.chop(1); if (!q_SSL_ctrl(ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, ace.data())) qCWarning(lcSsl, "could not set SSL_CTRL_SET_TLSEXT_HOSTNAME, Server Name Indication disabled"); } @@ -632,10 +636,12 @@ void QSslSocketPrivate::resetDefaultCiphers() // Unconditionally exclude ADH and AECDH ciphers since they offer no MITM protection if (!ciph.name().toLower().startsWith(QLatin1String("adh")) && !ciph.name().toLower().startsWith(QLatin1String("exp-adh")) && - !ciph.name().toLower().startsWith(QLatin1String("aecdh"))) + !ciph.name().toLower().startsWith(QLatin1String("aecdh"))) { ciphers << ciph; - if (ciph.usedBits() >= 128) - defaultCiphers << ciph; + + if (ciph.usedBits() >= 128) + defaultCiphers << ciph; + } } } } diff --git a/src/platformsupport/clipboard/qmacmime.mm b/src/platformsupport/clipboard/qmacmime.mm index 8a750b8dcb..2ad734b8b9 100644 --- a/src/platformsupport/clipboard/qmacmime.mm +++ b/src/platformsupport/clipboard/qmacmime.mm @@ -643,7 +643,7 @@ QList<QByteArray> QMacPasteboardMimeFileUri::convertFromMime(const QString &mime QUrl url = urls.at(i).toUrl(); if (url.scheme().isEmpty()) url.setScheme(QLatin1String("file")); - if (url.scheme().toLower() == QLatin1String("file")) { + if (url.scheme() == QLatin1String("file")) { if (url.host().isEmpty()) url.setHost(QLatin1String("localhost")); url.setPath(url.path().normalized(QString::NormalizationForm_D)); @@ -722,7 +722,7 @@ QList<QByteArray> QMacPasteboardMimeUrl::convertFromMime(const QString &mime, QV QUrl url = urls.at(i).toUrl(); if (url.scheme().isEmpty()) url.setScheme(QLatin1String("file")); - if (url.scheme().toLower() == QLatin1String("file")) { + if (url.scheme() == QLatin1String("file")) { if (url.host().isEmpty()) url.setHost(QLatin1String("localhost")); url.setPath(url.path().normalized(QString::NormalizationForm_D)); diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h index 18673a3667..fa05626d18 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h @@ -57,7 +57,11 @@ public: QPaintDevice *paintDevice() Q_DECL_OVERRIDE; void flush(QWindow *widget, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE; +#ifndef QT_NO_OPENGL QImage toImage() const Q_DECL_OVERRIDE; +#else + QImage toImage() const; // No QPlatformBackingStore::toImage() for NO_OPENGL builds. +#endif void resize (const QSize &size, const QRegion &) Q_DECL_OVERRIDE; bool scroll(const QRegion &area, int dx, int dy) Q_DECL_OVERRIDE; void beginPaint(const QRegion ®ion) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index f98ddbb14f..c021a551a7 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -428,14 +428,18 @@ void QCocoaIntegration::updateScreens() } siblings << screen; } + + // Set virtual siblings list. All screens in mScreens are siblings, because we ignored the + // mirrors. Note that some of the screens we update the siblings list for here may be deleted + // below, but update anyway to keep the to-be-deleted screens out of the siblings list. + foreach (QCocoaScreen* screen, mScreens) + screen->setVirtualSiblings(siblings); + // Now the leftovers in remainingScreens are no longer current, so we can delete them. foreach (QCocoaScreen* screen, remainingScreens) { mScreens.removeOne(screen); destroyScreen(screen); } - // All screens in mScreens are siblings, because we ignored the mirrors. - foreach (QCocoaScreen* screen, mScreens) - screen->setVirtualSiblings(siblings); } QCocoaScreen *QCocoaIntegration::screenAtIndex(int index) diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h index 64299c6cd2..64eeabcc2d 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.h +++ b/src/plugins/platforms/cocoa/qcocoamenu.h @@ -81,8 +81,6 @@ public: inline NSMenu *nsMenu() const { return m_nativeMenu; } - inline NSMenuItem *nsMenuItem() const - { return m_nativeItem; } inline bool isVisible() const { return m_visible; } @@ -91,11 +89,9 @@ public: QList<QCocoaMenuItem *> items() const; QList<QCocoaMenuItem *> merged() const; - void setMenuBar(QCocoaMenuBar *menuBar); - QCocoaMenuBar *menuBar() const; - void setContainingMenuItem(QCocoaMenuItem *menuItem); - QCocoaMenuItem *containingMenuItem() const; + void setAttachedItem(NSMenuItem *item); + NSMenuItem *attachedItem() const; private: QCocoaMenuItem *itemOrNull(int index) const; @@ -103,13 +99,10 @@ private: QList<QCocoaMenuItem *> m_menuItems; NSMenu *m_nativeMenu; - NSMenuItem *m_nativeItem; - NSObject *m_delegate; + NSMenuItem *m_attachedItem; bool m_enabled; bool m_visible; quintptr m_tag; - QCocoaMenuBar *m_menuBar; - QCocoaMenuItem *m_containingMenuItem; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 8c576c7cbe..3fc98c071f 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -102,6 +102,28 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate); return self; } +- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu +{ + Q_ASSERT(m_menu->nsMenu() == menu); + return m_menu->items().count(); +} + +- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel +{ + Q_UNUSED(index); + Q_ASSERT(m_menu->nsMenu() == menu); + if (shouldCancel) { + // TODO detach all submenus + return NO; + } + + QCocoaMenuItem *menuItem = reinterpret_cast<QCocoaMenuItem *>(item.tag); + if (m_menu->items().contains(menuItem)) { + if (QCocoaMenu *itemSubmenu = menuItem->menu()) + itemSubmenu->setAttachedItem(item); + } + return YES; +} - (void)menu:(NSMenu*)menu willHighlightItem:(NSMenuItem*)item { @@ -234,20 +256,16 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate); QT_BEGIN_NAMESPACE QCocoaMenu::QCocoaMenu() : + m_attachedItem(0), m_enabled(true), m_visible(true), - m_tag(0), - m_menuBar(0), - m_containingMenuItem(0) + m_tag(0) { QMacAutoReleasePool pool; - m_delegate = [[QCocoaMenuDelegate alloc] initWithMenu:this]; - m_nativeItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; m_nativeMenu = [[NSMenu alloc] initWithTitle:@"Untitled"]; [m_nativeMenu setAutoenablesItems:YES]; - m_nativeMenu.delegate = (QCocoaMenuDelegate *) m_delegate; - [m_nativeItem setSubmenu:m_nativeMenu]; + m_nativeMenu.delegate = [[QCocoaMenuDelegate alloc] initWithMenu:this]; } QCocoaMenu::~QCocoaMenu() @@ -257,14 +275,11 @@ QCocoaMenu::~QCocoaMenu() SET_COCOA_MENU_ANCESTOR(item, 0); } - if (m_containingMenuItem) - m_containingMenuItem->clearMenu(this); - QMacAutoReleasePool pool; - [m_nativeItem setSubmenu:nil]; + NSObject *delegate = m_nativeMenu.delegate; + m_nativeMenu.delegate = nil; + [delegate release]; [m_nativeMenu release]; - [m_delegate release]; - [m_nativeItem release]; } void QCocoaMenu::setText(const QString &text) @@ -272,7 +287,6 @@ void QCocoaMenu::setText(const QString &text) QMacAutoReleasePool pool; QString stripped = qt_mac_removeAmpersandEscapes(text); [m_nativeMenu setTitle:QCFString::toNSString(stripped)]; - [m_nativeItem setTitle:QCFString::toNSString(stripped)]; } void QCocoaMenu::setMinimumWidth(int width) @@ -313,17 +327,13 @@ void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem * void QCocoaMenu::insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem) { - [item->nsItem() setTarget:m_delegate]; + item->nsItem().target = m_nativeMenu.delegate; if (!item->menu()) [item->nsItem() setAction:@selector(itemFired:)]; if (item->isMerged()) return; - if ([item->nsItem() menu]) { - qWarning("Menu item is already in a menu, remove it from the other menu first before inserting"); - return; - } // if the item we're inserting before is merged, skip along until // we find a non-merged real item to insert ahead of. while (beforeItem && beforeItem->isMerged()) { @@ -451,12 +461,11 @@ void QCocoaMenu::setEnabled(bool enabled) bool QCocoaMenu::isEnabled() const { - return [m_nativeItem isEnabled]; + return m_attachedItem ? [m_attachedItem isEnabled] : m_enabled; } void QCocoaMenu::setVisible(bool visible) { - [m_nativeItem setSubmenu:(visible ? m_nativeMenu : nil)]; m_visible = visible; } @@ -593,8 +602,6 @@ void QCocoaMenu::syncModalState(bool modal) if (!m_enabled) modal = true; - [m_nativeItem setEnabled:!modal]; - foreach (QCocoaMenuItem *item, m_menuItems) { if (item->menu()) { // recurse into submenus item->menu()->syncModalState(modal); @@ -605,25 +612,24 @@ void QCocoaMenu::syncModalState(bool modal) } } -void QCocoaMenu::setMenuBar(QCocoaMenuBar *menuBar) +void QCocoaMenu::setAttachedItem(NSMenuItem *item) { - m_menuBar = menuBar; - SET_COCOA_MENU_ANCESTOR(this, menuBar); -} + if (item == m_attachedItem) + return; -QCocoaMenuBar *QCocoaMenu::menuBar() const -{ - return m_menuBar; -} + if (m_attachedItem) + m_attachedItem.submenu = nil; + + m_attachedItem = item; + + if (m_attachedItem) + m_attachedItem.submenu = m_nativeMenu; -void QCocoaMenu::setContainingMenuItem(QCocoaMenuItem *menuItem) -{ - m_containingMenuItem = menuItem; } -QCocoaMenuItem *QCocoaMenu::containingMenuItem() const +NSMenuItem *QCocoaMenu::attachedItem() const { - return m_containingMenuItem; + return m_attachedItem; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.h b/src/plugins/platforms/cocoa/qcocoamenubar.h index 0521bcd430..7ce2059450 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.h +++ b/src/plugins/platforms/cocoa/qcocoamenubar.h @@ -77,10 +77,10 @@ private: static QCocoaMenuBar *findGlobalMenubar(); bool shouldDisable(QCocoaWindow *active) const; - void insertNativeMenu(QCocoaMenu *menu, QCocoaMenu *beforeMenu); - void removeNativeMenu(QCocoaMenu *menu); - QList<QCocoaMenu*> m_menus; + NSMenuItem *nativeItemForMenu(QCocoaMenu *menu) const; + + QList<QPointer<QCocoaMenu> > m_menus; NSMenu *m_nativeMenu; QCocoaWindow *m_window; }; diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index c9a42e9d8e..e8b3823012 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -57,7 +57,6 @@ static inline QCocoaMenuLoader *getMenuLoader() return [NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)]; } - QCocoaMenuBar::QCocoaMenuBar() : m_window(0) { @@ -74,11 +73,20 @@ QCocoaMenuBar::~QCocoaMenuBar() #ifdef QT_COCOA_ENABLE_MENU_DEBUG qDebug() << "~QCocoaMenuBar" << this; #endif + foreach (QCocoaMenu *menu, m_menus) { + if (!menu) + continue; + NSMenuItem *item = nativeItemForMenu(menu); + if (menu->attachedItem() == item) + menu->setAttachedItem(nil); + } + [m_nativeMenu release]; static_menubars.removeOne(this); if (m_window && m_window->menubar() == this) { m_window->setMenubar(0); + // Delete the children first so they do not cause // the native menu items to be hidden after // the menu bar was updated @@ -87,24 +95,6 @@ QCocoaMenuBar::~QCocoaMenuBar() } } -void QCocoaMenuBar::insertNativeMenu(QCocoaMenu *menu, QCocoaMenu *beforeMenu) -{ - QMacAutoReleasePool pool; - - if (beforeMenu) { - NSUInteger nativeIndex = [m_nativeMenu indexOfItem:beforeMenu->nsMenuItem()]; - [m_nativeMenu insertItem: menu->nsMenuItem() atIndex: nativeIndex]; - } else { - [m_nativeMenu addItem: menu->nsMenuItem()]; - } - - menu->setMenuBar(this); - syncMenu(static_cast<QPlatformMenu *>(menu)); - if (menu->isVisible()) { - [m_nativeMenu setSubmenu: menu->nsMenu() forItem: menu->nsMenuItem()]; - } -} - void QCocoaMenuBar::insertMenu(QPlatformMenu *platformMenu, QPlatformMenu *before) { QCocoaMenu *menu = static_cast<QCocoaMenu *>(platformMenu); @@ -113,31 +103,40 @@ void QCocoaMenuBar::insertMenu(QPlatformMenu *platformMenu, QPlatformMenu *befor qDebug() << "QCocoaMenuBar" << this << "insertMenu" << menu << "before" << before; #endif - if (m_menus.contains(menu)) { + if (m_menus.contains(QPointer<QCocoaMenu>(menu))) { qWarning("This menu already belongs to the menubar, remove it first"); return; } - if (beforeMenu && !m_menus.contains(beforeMenu)) { + if (beforeMenu && !m_menus.contains(QPointer<QCocoaMenu>(beforeMenu))) { qWarning("The before menu does not belong to the menubar"); return; } - m_menus.insert(beforeMenu ? m_menus.indexOf(beforeMenu) : m_menus.size(), menu); - if (!menu->menuBar()) - insertNativeMenu(menu, beforeMenu); - if (m_window && m_window->window()->isActive()) - updateMenuBarImmediately(); -} + int insertionIndex = beforeMenu ? m_menus.indexOf(beforeMenu) : m_menus.size(); + m_menus.insert(insertionIndex, menu); + + { + QMacAutoReleasePool pool; + NSMenuItem *item = [[[NSMenuItem alloc] init] autorelease]; + item.tag = reinterpret_cast<NSInteger>(menu); + + if (beforeMenu) { + // QMenuBar::toNSMenu() exposes the native menubar and + // the user could have inserted its own items in there. + // Same remark applies to removeMenu(). + NSMenuItem *beforeItem = nativeItemForMenu(beforeMenu); + NSInteger nativeIndex = [m_nativeMenu indexOfItem:beforeItem]; + [m_nativeMenu insertItem:item atIndex:nativeIndex]; + } else { + [m_nativeMenu addItem:item]; + } + } -void QCocoaMenuBar::removeNativeMenu(QCocoaMenu *menu) -{ - QMacAutoReleasePool pool; + syncMenu(menu); - if (menu->menuBar() == this) - menu->setMenuBar(0); - NSUInteger realIndex = [m_nativeMenu indexOfItem:menu->nsMenuItem()]; - [m_nativeMenu removeItemAtIndex: realIndex]; + if (m_window && m_window->window()->isActive()) + updateMenuBarImmediately(); } void QCocoaMenuBar::removeMenu(QPlatformMenu *platformMenu) @@ -147,8 +146,17 @@ void QCocoaMenuBar::removeMenu(QPlatformMenu *platformMenu) qWarning("Trying to remove a menu that does not belong to the menubar"); return; } + + NSMenuItem *item = nativeItemForMenu(menu); + if (menu->attachedItem() == item) + menu->setAttachedItem(nil); m_menus.removeOne(menu); - removeNativeMenu(menu); + + QMacAutoReleasePool pool; + + // See remark in insertMenu(). + NSInteger nativeIndex = [m_nativeMenu indexOfItem:item]; + [m_nativeMenu removeItemAtIndex:nativeIndex]; } void QCocoaMenuBar::syncMenu(QPlatformMenu *menu) @@ -170,7 +178,16 @@ void QCocoaMenuBar::syncMenu(QPlatformMenu *menu) break; } } - [cocoaMenu->nsMenuItem() setHidden:shouldHide]; + + nativeItemForMenu(cocoaMenu).hidden = shouldHide; +} + +NSMenuItem *QCocoaMenuBar::nativeItemForMenu(QCocoaMenu *menu) const +{ + if (!menu) + return nil; + + return [m_nativeMenu itemWithTag:reinterpret_cast<NSInteger>(menu)]; } void QCocoaMenuBar::handleReparent(QWindow *newParentWindow) @@ -297,24 +314,16 @@ void QCocoaMenuBar::updateMenuBarImmediately() qDebug() << "QCocoaMenuBar" << "updateMenuBarImmediately" << cw; #endif bool disableForModal = mb->shouldDisable(cw); - // force a sync? - foreach (QCocoaMenu *m, mb->m_menus) { - mb->syncMenu(m); - m->syncModalState(disableForModal); - } - // reparent shared menu items if necessary. - // We browse the list in reverse order to be sure that the next items are redrawn before the current ones, - // in this way we are sure that "beforeMenu" (see below) is part of the native menu before "m" is redraw - for (int i = mb->m_menus.size() - 1; i >= 0; i--) { - QCocoaMenu *m = mb->m_menus.at(i); - QCocoaMenuBar *menuBar = m->menuBar(); - if (menuBar != mb) { - QCocoaMenu *beforeMenu = i < (mb->m_menus.size() - 1) ? mb->m_menus.at(i + 1) : 0; - if (menuBar) - menuBar->removeNativeMenu(m); - mb->insertNativeMenu(m, beforeMenu); - } + foreach (QCocoaMenu *menu, mb->m_menus) { + if (!menu) + continue; + NSMenuItem *item = mb->nativeItemForMenu(menu); + menu->setAttachedItem(item); + SET_COCOA_MENU_ANCESTOR(menu, mb); + // force a sync? + mb->syncMenu(menu); + menu->syncModalState(disableForModal); } QCocoaMenuLoader *loader = getMenuLoader(); diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.h b/src/plugins/platforms/cocoa/qcocoamenuitem.h index 0d6f67959b..bba9ce3963 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.h +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.h @@ -93,7 +93,6 @@ public: inline bool isSeparator() const { return m_isSeparator; } QCocoaMenu *menu() const { return m_menu; } - void clearMenu(QCocoaMenu *menu); MenuRole effectiveRole() const; private: @@ -105,7 +104,7 @@ private: QString m_text; bool m_textSynced; QIcon m_icon; - QCocoaMenu *m_menu; + QPointer<QCocoaMenu> m_menu; bool m_isVisible; bool m_enabled; bool m_isSeparator; diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index 9e4f0b9ad1..de0271ce4d 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -142,15 +142,12 @@ void QCocoaMenuItem::setMenu(QPlatformMenu *menu) if (m_menu) { if (COCOA_MENU_ANCESTOR(m_menu) == this) SET_COCOA_MENU_ANCESTOR(m_menu, 0); - if (m_menu->containingMenuItem() == this) - m_menu->setContainingMenuItem(0); } QMacAutoReleasePool pool; m_menu = static_cast<QCocoaMenu *>(menu); if (m_menu) { SET_COCOA_MENU_ANCESTOR(m_menu, this); - m_menu->setContainingMenuItem(this); } else { // we previously had a menu, but no longer // clear out our item so the nexy sync() call builds a new one @@ -159,12 +156,6 @@ void QCocoaMenuItem::setMenu(QPlatformMenu *menu) } } -void QCocoaMenuItem::clearMenu(QCocoaMenu *menu) -{ - if (menu == m_menu) - m_menu = 0; -} - void QCocoaMenuItem::setVisible(bool isVisible) { m_isVisible = isVisible; @@ -226,14 +217,6 @@ NSMenuItem *QCocoaMenuItem::sync() m_native = nil; } - if (m_menu) { - if (m_native != m_menu->nsMenuItem()) { - [m_native release]; - m_native = [m_menu->nsMenuItem() retain]; - [m_native setTag:reinterpret_cast<NSInteger>(this)]; - } - } - if ((m_role != NoRole && !m_textSynced) || m_merged) { NSMenuItem *mergeItem = nil; QCocoaMenuLoader *loader = getMenuLoader(); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index eb65f7e061..b501358acc 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -414,6 +414,7 @@ QCocoaWindow::~QCocoaWindow() #endif QMacAutoReleasePool pool; + [m_nsWindow makeFirstResponder:nil]; [m_nsWindow setContentView:nil]; [m_nsWindow.helper detachFromPlatformWindow]; if (m_isNSWindowChild) { @@ -1004,7 +1005,15 @@ void QCocoaWindow::raise() [parentNSWindow removeChildWindow:m_nsWindow]; [parentNSWindow addChildWindow:m_nsWindow ordered:NSWindowAbove]; } else { - [m_nsWindow orderFront: m_nsWindow]; + { + // Clean up autoreleased temp objects from orderFront immediately. + // Failure to do so has been observed to cause leaks also beyond any outer + // autorelease pool (for example around a complete QWindow + // construct-show-raise-hide-delete cyle), counter to expected autoreleasepool + // behavior. + QMacAutoReleasePool pool; + [m_nsWindow orderFront: m_nsWindow]; + } static bool raiseProcess = qt_mac_resolveOption(true, "QT_MAC_SET_RAISE_PROCESS"); if (raiseProcess) { ProcessSerialNumber psn; diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index 48de7d56f8..5b2370b69d 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -1253,7 +1253,12 @@ QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const { QList<int> result; - const KeyboardLayoutItem &kbItem = keyLayout[e->nativeVirtualKey()]; + + const quint32 nativeVirtualKey = e->nativeVirtualKey(); + if (nativeVirtualKey > 255) + return result; + + const KeyboardLayoutItem &kbItem = keyLayout[nativeVirtualKey]; if (!kbItem.exists) return result; diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 4c4d553b2d..47e68ae0af 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -39,8 +39,10 @@ #include "qwinrtbackingstore.h" #include "qwinrtinputcontext.h" #include "qwinrtcursor.h" +#include "qwinrtwindow.h" #include <private/qeventdispatcher_winrt_p.h> +#include <QtCore/QLoggingCategory> #include <QtGui/QSurfaceFormat> #include <QtGui/QGuiApplication> #include <qpa/qwindowsysteminterface.h> @@ -469,6 +471,7 @@ QWinRTScreen::QWinRTScreen() : d_ptr(new QWinRTScreenPrivate) { Q_D(QWinRTScreen); + qCDebug(lcQpaWindows) << __FUNCTION__; d->orientation = Qt::PrimaryOrientation; d->touchDevice = Q_NULLPTR; @@ -553,6 +556,7 @@ QWinRTScreen::QWinRTScreen() QWinRTScreen::~QWinRTScreen() { Q_D(QWinRTScreen); + qCDebug(lcQpaWindows) << __FUNCTION__ << this; // Unregister callbacks HRESULT hr; @@ -631,6 +635,12 @@ QDpi QWinRTScreen::logicalDpi() const return QDpi(d->logicalDpi, d->logicalDpi); } +qreal QWinRTScreen::pixelDensity() const +{ + Q_D(const QWinRTScreen); + return qRound(d->logicalDpi / 96); +} + qreal QWinRTScreen::scaleFactor() const { Q_D(const QWinRTScreen); @@ -697,6 +707,8 @@ Xaml::IDependencyObject *QWinRTScreen::canvas() const void QWinRTScreen::setStatusBarVisibility(bool visible, QWindow *window) { Q_D(QWinRTScreen); + qCDebug(lcQpaWindows) << __FUNCTION__ << window << visible; + const Qt::WindowFlags windowType = window->flags() & Qt::WindowType_Mask; if (!window || (windowType != Qt::Window && windowType != Qt::Dialog)) return; @@ -768,6 +780,7 @@ QWindow *QWinRTScreen::topWindow() const void QWinRTScreen::addWindow(QWindow *window) { Q_D(QWinRTScreen); + qCDebug(lcQpaWindows) << __FUNCTION__ << window; if (window == topWindow()) return; @@ -785,6 +798,7 @@ void QWinRTScreen::addWindow(QWindow *window) void QWinRTScreen::removeWindow(QWindow *window) { Q_D(QWinRTScreen); + qCDebug(lcQpaWindows) << __FUNCTION__ << window; #ifdef Q_OS_WINPHONE if (window->visibility() == QWindow::Minimized) @@ -1131,6 +1145,7 @@ HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs * hr = d->coreWindow->get_Bounds(&size); RETURN_OK_IF_FAILED("Failed to get window bounds"); d->logicalSize = QSizeF(size.Width, size.Height); + qCDebug(lcQpaWindows) << __FUNCTION__ << d->logicalSize; QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry()); QPlatformScreen::resizeMaximizedWindows(); handleExpose(); @@ -1140,6 +1155,7 @@ HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs * HRESULT QWinRTScreen::onActivated(ICoreWindow *, IWindowActivatedEventArgs *args) { Q_D(QWinRTScreen); + qCDebug(lcQpaWindows) << __FUNCTION__; CoreWindowActivationState activationState; args->get_WindowActivationState(&activationState); @@ -1159,6 +1175,8 @@ HRESULT QWinRTScreen::onActivated(ICoreWindow *, IWindowActivatedEventArgs *args HRESULT QWinRTScreen::onClosed(ICoreWindow *, ICoreWindowEventArgs *) { + qCDebug(lcQpaWindows) << __FUNCTION__; + foreach (QWindow *w, QGuiApplication::topLevelWindows()) QWindowSystemInterface::handleCloseEvent(w); return S_OK; @@ -1170,6 +1188,7 @@ HRESULT QWinRTScreen::onVisibilityChanged(ICoreWindow *, IVisibilityChangedEvent boolean visible; HRESULT hr = args ? args->get_Visible(&visible) : d->coreWindow->get_Visible(&visible); RETURN_OK_IF_FAILED("Failed to get visibility."); + qCDebug(lcQpaWindows) << __FUNCTION__ << visible; QWindowSystemInterface::handleApplicationStateChanged(visible ? Qt::ApplicationActive : Qt::ApplicationHidden); if (visible) handleExpose(); @@ -1179,7 +1198,7 @@ HRESULT QWinRTScreen::onVisibilityChanged(ICoreWindow *, IVisibilityChangedEvent HRESULT QWinRTScreen::onOrientationChanged(IDisplayInformation *, IInspectable *) { Q_D(QWinRTScreen); - + qCDebug(lcQpaWindows) << __FUNCTION__; DisplayOrientations displayOrientation; HRESULT hr = d->displayInformation->get_CurrentOrientation(&displayOrientation); RETURN_OK_IF_FAILED("Failed to get current orientations."); @@ -1187,7 +1206,8 @@ HRESULT QWinRTScreen::onOrientationChanged(IDisplayInformation *, IInspectable * Qt::ScreenOrientation newOrientation = static_cast<Qt::ScreenOrientation>(static_cast<int>(qtOrientationsFromNative(displayOrientation))); if (d->orientation != newOrientation) { d->orientation = newOrientation; -#ifdef Q_OS_WINPHONE + qCDebug(lcQpaWindows) << " New orientation:" << newOrientation; +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) onSizeChanged(nullptr, nullptr); #endif QWindowSystemInterface::handleScreenOrientationChange(screen(), d->orientation); @@ -1211,6 +1231,8 @@ HRESULT QWinRTScreen::onDpiChanged(IDisplayInformation *, IInspectable *) hr = d->displayInformation->get_ResolutionScale(&resolutionScale); d->scaleFactor = qreal(resolutionScale) / 100; #endif + qCDebug(lcQpaWindows) << __FUNCTION__ << "Scale Factor:" << d->scaleFactor; + RETURN_OK_IF_FAILED("Failed to get scale factor"); FLOAT dpi; @@ -1225,6 +1247,8 @@ HRESULT QWinRTScreen::onDpiChanged(IDisplayInformation *, IInspectable *) hr = d->displayInformation->get_RawDpiY(&dpi); RETURN_OK_IF_FAILED("Failed to get y raw DPI."); d->physicalDpi.second = dpi ? dpi : 96.0; + qCDebug(lcQpaWindows) << __FUNCTION__ << "Logical DPI:" << d->logicalDpi + << "Physical DPI:" << d->physicalDpi; return S_OK; } @@ -1232,12 +1256,14 @@ HRESULT QWinRTScreen::onDpiChanged(IDisplayInformation *, IInspectable *) #ifdef Q_OS_WINPHONE HRESULT QWinRTScreen::onStatusBarShowing(IStatusBar *, IInspectable *) { + qCDebug(lcQpaWindows) << __FUNCTION__; onSizeChanged(nullptr, nullptr); return S_OK; } HRESULT QWinRTScreen::onStatusBarHiding(IStatusBar *, IInspectable *) { + qCDebug(lcQpaWindows) << __FUNCTION__; onSizeChanged(nullptr, nullptr); return S_OK; } diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h index 0043b2cfa3..ac9db9bfef 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.h +++ b/src/plugins/platforms/winrt/qwinrtscreen.h @@ -93,6 +93,7 @@ public: QImage::Format format() const Q_DECL_OVERRIDE; QSizeF physicalSize() const Q_DECL_OVERRIDE; QDpi logicalDpi() const Q_DECL_OVERRIDE; + qreal pixelDensity() const Q_DECL_OVERRIDE; qreal scaleFactor() const; QPlatformCursor *cursor() const Q_DECL_OVERRIDE; Qt::KeyboardModifiers keyboardModifiers() const; diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 9409de2406..ea20ef7a04 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -429,6 +429,7 @@ void QXcbDrag::move(const QPoint &globalPos) xcb_client_message_event_t enter; enter.response_type = XCB_CLIENT_MESSAGE; + enter.sequence = 0; enter.window = target; enter.format = 32; enter.type = atom(QXcbAtom::XdndEnter); @@ -457,6 +458,7 @@ void QXcbDrag::move(const QPoint &globalPos) xcb_client_message_event_t move; move.response_type = XCB_CLIENT_MESSAGE; + move.sequence = 0; move.window = target; move.format = 32; move.type = atom(QXcbAtom::XdndPosition); @@ -485,6 +487,7 @@ void QXcbDrag::drop(const QPoint &globalPos) xcb_client_message_event_t drop; drop.response_type = XCB_CLIENT_MESSAGE; + drop.sequence = 0; drop.window = current_target; drop.format = 32; drop.type = atom(QXcbAtom::XdndDrop); @@ -746,6 +749,7 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message xcb_client_message_event_t response; response.response_type = XCB_CLIENT_MESSAGE; + response.sequence = 0; response.window = xdnd_dragsource; response.format = 32; response.type = atom(QXcbAtom::XdndStatus); @@ -892,6 +896,7 @@ void QXcbDrag::send_leave() xcb_client_message_event_t leave; leave.response_type = XCB_CLIENT_MESSAGE; + leave.sequence = 0; leave.window = current_target; leave.format = 32; leave.type = atom(QXcbAtom::XdndLeave); @@ -962,6 +967,7 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e xcb_client_message_event_t finished; finished.response_type = XCB_CLIENT_MESSAGE; + finished.sequence = 0; finished.window = xdnd_dragsource; finished.format = 32; finished.type = atom(QXcbAtom::XdndFinished); diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 18b0667390..67a9b2f190 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -367,6 +367,7 @@ void QXcbScreen::sendStartupMessage(const QByteArray &message) const ev.response_type = XCB_CLIENT_MESSAGE; ev.format = 8; ev.type = connection()->atom(QXcbAtom::_NET_STARTUP_INFO_BEGIN); + ev.sequence = 0; ev.window = rootWindow; int sent = 0; int length = message.length() + 1; // include NUL byte diff --git a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp index cfed556ec9..5522af86de 100644 --- a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp +++ b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp @@ -100,9 +100,9 @@ xcb_window_t QXcbSystemTrayTracker::locateTrayWindow(const QXcbConnection *conne void QXcbSystemTrayTracker::requestSystemTrayWindowDock(xcb_window_t window) const { xcb_client_message_event_t trayRequest; - memset(&trayRequest, 0, sizeof(trayRequest)); trayRequest.response_type = XCB_CLIENT_MESSAGE; trayRequest.format = 32; + trayRequest.sequence = 0; trayRequest.window = m_trayWindow; trayRequest.type = m_trayAtom; trayRequest.data.data32[0] = XCB_CURRENT_TIME; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 42e7d5da2c..13eecbfb4f 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1111,21 +1111,37 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates() void QXcbWindow::setNetWmStates(NetWmStates states) { QVector<xcb_atom_t> atoms; - if (states & NetWmStateAbove) + + xcb_get_property_cookie_t get_cookie = + xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_STATE), + XCB_ATOM_ATOM, 0, 1024); + + xcb_get_property_reply_t *reply = + xcb_get_property_reply(xcb_connection(), get_cookie, NULL); + + if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM && reply->value_len > 0) { + const xcb_atom_t *data = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply)); + atoms.resize(reply->value_len); + memcpy((void *)&atoms.first(), (void *)data, reply->value_len * sizeof(xcb_atom_t)); + } + + free(reply); + + if (states & NetWmStateAbove && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_ABOVE))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE)); - if (states & NetWmStateBelow) + if (states & NetWmStateBelow && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_BELOW))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_BELOW)); - if (states & NetWmStateFullScreen) + if (states & NetWmStateFullScreen && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)); - if (states & NetWmStateMaximizedHorz) + if (states & NetWmStateMaximizedHorz && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ)); - if (states & NetWmStateMaximizedVert) + if (states & NetWmStateMaximizedVert && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT)); - if (states & NetWmStateModal) + if (states & NetWmStateModal && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MODAL))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MODAL)); - if (states & NetWmStateStaysOnTop) + if (states & NetWmStateStaysOnTop && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP)); - if (states & NetWmStateDemandsAttention) + if (states & NetWmStateDemandsAttention && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)); if (atoms.isEmpty()) { @@ -1245,6 +1261,7 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two) event.response_type = XCB_CLIENT_MESSAGE; event.format = 32; + event.sequence = 0; event.window = m_window; event.type = atom(QXcbAtom::_NET_WM_STATE); event.data.data32[0] = set ? 1 : 0; @@ -1286,6 +1303,7 @@ void QXcbWindow::setWindowState(Qt::WindowState state) event.response_type = XCB_CLIENT_MESSAGE; event.format = 32; + event.sequence = 0; event.window = m_window; event.type = atom(QXcbAtom::WM_CHANGE_STATE); event.data.data32[0] = XCB_WM_STATE_ICONIC; @@ -1690,6 +1708,7 @@ void QXcbWindow::requestActivateWindow() event.response_type = XCB_CLIENT_MESSAGE; event.format = 32; + event.sequence = 0; event.window = m_window; event.type = atom(QXcbAtom::_NET_ACTIVE_WINDOW); event.data.data32[0] = 1; @@ -2636,6 +2655,7 @@ bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner) xcb_client_message_event_t xev; xev.response_type = XCB_CLIENT_MESSAGE; xev.type = moveResize; + xev.sequence = 0; xev.window = xcb_window(); xev.format = 32; const QPoint globalPos = window()->mapToGlobal(pos); @@ -2664,6 +2684,7 @@ void QXcbWindow::sendXEmbedMessage(xcb_window_t window, quint32 message, event.response_type = XCB_CLIENT_MESSAGE; event.format = 32; + event.sequence = 0; event.window = window; event.type = atom(QXcbAtom::_XEMBED); event.data.data32[0] = connection()->time(); diff --git a/src/sql/kernel/qsqlresult.h b/src/sql/kernel/qsqlresult.h index ad5f615a52..c6611c925f 100644 --- a/src/sql/kernel/qsqlresult.h +++ b/src/sql/kernel/qsqlresult.h @@ -44,6 +44,9 @@ #include <QtCore/qvector.h> #include <QtSql/qsql.h> +// for testing: +class tst_QSqlQuery; + QT_BEGIN_NAMESPACE @@ -60,6 +63,8 @@ class Q_SQL_EXPORT QSqlResult Q_DECLARE_PRIVATE(QSqlResult) friend class QSqlQuery; friend class QSqlTableModelPrivate; + // for testing: + friend class ::tst_QSqlQuery; public: virtual ~QSqlResult(); diff --git a/src/testlib/Qt5TestConfigExtras.cmake.in b/src/testlib/Qt5TestConfigExtras.cmake.in new file mode 100644 index 0000000000..2a575958ae --- /dev/null +++ b/src/testlib/Qt5TestConfigExtras.cmake.in @@ -0,0 +1,5 @@ + +set_property(TARGET Qt5::Test + APPEND PROPERTY + INTERFACE_COMPILE_DEFINITIONS QT_TESTCASE_BUILDDIR=\\\"\${CMAKE_BINARY_DIR}\\\" +) diff --git a/src/widgets/dialogs/qerrormessage.cpp b/src/widgets/dialogs/qerrormessage.cpp index c5e764236a..77d9eb29ac 100644 --- a/src/widgets/dialogs/qerrormessage.cpp +++ b/src/widgets/dialogs/qerrormessage.cpp @@ -402,4 +402,6 @@ void QErrorMessagePrivate::retranslateStrings() QT_END_NAMESPACE +#include "moc_qerrormessage.cpp" + #endif // QT_NO_ERRORMESSAGE diff --git a/src/widgets/dialogs/qfileinfogatherer.cpp b/src/widgets/dialogs/qfileinfogatherer.cpp index b20db8fc7c..014792ea93 100644 --- a/src/widgets/dialogs/qfileinfogatherer.cpp +++ b/src/widgets/dialogs/qfileinfogatherer.cpp @@ -345,3 +345,5 @@ void QFileInfoGatherer::fetch(const QFileInfo &fileInfo, QElapsedTimer &base, bo #endif // QT_NO_FILESYSTEMMODEL QT_END_NAMESPACE + +#include "moc_qfileinfogatherer_p.cpp" diff --git a/src/widgets/dialogs/qsidebar.cpp b/src/widgets/dialogs/qsidebar.cpp index 1b1eb6472e..d86cddab61 100644 --- a/src/widgets/dialogs/qsidebar.cpp +++ b/src/widgets/dialogs/qsidebar.cpp @@ -515,4 +515,6 @@ bool QSidebar::event(QEvent * event) QT_END_NAMESPACE +#include "moc_qsidebar_p.cpp" + #endif diff --git a/src/widgets/effects/qgraphicseffect.cpp b/src/widgets/effects/qgraphicseffect.cpp index abeb153e53..4d1d1e9896 100644 --- a/src/widgets/effects/qgraphicseffect.cpp +++ b/src/widgets/effects/qgraphicseffect.cpp @@ -1235,4 +1235,7 @@ void QGraphicsOpacityEffect::draw(QPainter *painter) QT_END_NAMESPACE +#include "moc_qgraphicseffect.cpp" +#include "moc_qgraphicseffect_p.cpp" + #endif //QT_NO_GRAPHICSEFFECT diff --git a/src/widgets/effects/qpixmapfilter.cpp b/src/widgets/effects/qpixmapfilter.cpp index 1d4014cbae..1ff4f8e88a 100644 --- a/src/widgets/effects/qpixmapfilter.cpp +++ b/src/widgets/effects/qpixmapfilter.cpp @@ -1345,4 +1345,6 @@ void QPixmapDropShadowFilter::draw(QPainter *p, QT_END_NAMESPACE +#include "moc_qpixmapfilter_p.cpp" + #endif //QT_NO_GRAPHICSEFFECT diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout.cpp b/src/widgets/graphicsview/qgraphicsanchorlayout.cpp index f20203cd80..176ce694a0 100644 --- a/src/widgets/graphicsview/qgraphicsanchorlayout.cpp +++ b/src/widgets/graphicsview/qgraphicsanchorlayout.cpp @@ -529,4 +529,7 @@ QSizeF QGraphicsAnchorLayout::sizeHint(Qt::SizeHint which, const QSizeF &constra } QT_END_NAMESPACE + +#include "moc_qgraphicsanchorlayout.cpp" + #endif //QT_NO_GRAPHICSVIEW diff --git a/src/widgets/graphicsview/qgraphicsitemanimation.cpp b/src/widgets/graphicsview/qgraphicsitemanimation.cpp index 5e12e67a86..c5687ee9b3 100644 --- a/src/widgets/graphicsview/qgraphicsitemanimation.cpp +++ b/src/widgets/graphicsview/qgraphicsitemanimation.cpp @@ -594,4 +594,6 @@ void QGraphicsItemAnimation::afterAnimationStep(qreal step) QT_END_NAMESPACE +#include "moc_qgraphicsitemanimation.cpp" + #endif // QT_NO_GRAPHICSVIEW diff --git a/src/widgets/graphicsview/qgraphicsscenelinearindex.cpp b/src/widgets/graphicsview/qgraphicsscenelinearindex.cpp index bd09570c4a..06f9125612 100644 --- a/src/widgets/graphicsview/qgraphicsscenelinearindex.cpp +++ b/src/widgets/graphicsview/qgraphicsscenelinearindex.cpp @@ -91,3 +91,4 @@ Add the \a item from the index. */ +#include "moc_qgraphicsscenelinearindex_p.cpp" diff --git a/src/widgets/graphicsview/qgraphicswidget.cpp b/src/widgets/graphicsview/qgraphicswidget.cpp index e7fca55550..d52aff5131 100644 --- a/src/widgets/graphicsview/qgraphicswidget.cpp +++ b/src/widgets/graphicsview/qgraphicswidget.cpp @@ -2417,4 +2417,6 @@ void QGraphicsWidget::dumpFocusChain() QT_END_NAMESPACE +#include "moc_qgraphicswidget.cpp" + #endif //QT_NO_GRAPHICSVIEW diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index 9135d1a23c..da4492a684 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -4401,7 +4401,20 @@ QPixmap QAbstractItemViewPrivate::renderToPixmap(const QModelIndexList &indexes, QItemViewPaintPairs paintPairs = draggablePaintPairs(indexes, r); if (paintPairs.isEmpty()) return QPixmap(); - QPixmap pixmap(r->size()); + + qreal scale = 1.0f; + + Q_Q(const QAbstractItemView); + QWidget *window = q->window(); + if (window) { + QWindow *windowHandle = window->windowHandle(); + if (windowHandle) + scale = windowHandle->devicePixelRatio(); + } + + QPixmap pixmap(r->size() * scale); + pixmap.setDevicePixelRatio(scale); + pixmap.fill(Qt::transparent); QPainter painter(&pixmap); QStyleOptionViewItem option = viewOptionsV1(); diff --git a/src/widgets/itemviews/qcolumnviewgrip.cpp b/src/widgets/itemviews/qcolumnviewgrip.cpp index d2d1819cf7..f7d6e6d2b0 100644 --- a/src/widgets/itemviews/qcolumnviewgrip.cpp +++ b/src/widgets/itemviews/qcolumnviewgrip.cpp @@ -189,4 +189,6 @@ originalXLocation(-1) QT_END_NAMESPACE +#include "moc_qcolumnviewgrip_p.cpp" + #endif // QT_NO_QCOLUMNVIEW diff --git a/src/widgets/itemviews/qitemeditorfactory.cpp b/src/widgets/itemviews/qitemeditorfactory.cpp index 9b7de87e32..5356ce3ad0 100644 --- a/src/widgets/itemviews/qitemeditorfactory.cpp +++ b/src/widgets/itemviews/qitemeditorfactory.cpp @@ -613,4 +613,6 @@ QT_END_NAMESPACE #include "qitemeditorfactory.moc" #endif +#include "moc_qitemeditorfactory_p.cpp" + #endif // QT_NO_ITEMVIEWS diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index c7085a0dc2..3303aac6ed 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -3301,4 +3301,6 @@ QSize QListView::viewportSizeHint() const QT_END_NAMESPACE +#include "moc_qlistview.cpp" + #endif // QT_NO_LISTVIEW diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp index 434e819d9c..9b34e89ef0 100644 --- a/src/widgets/itemviews/qlistwidget.cpp +++ b/src/widgets/itemviews/qlistwidget.cpp @@ -1975,5 +1975,6 @@ bool QListWidget::event(QEvent *e) QT_END_NAMESPACE #include "moc_qlistwidget.cpp" +#include "moc_qlistwidget_p.cpp" #endif // QT_NO_LISTWIDGET diff --git a/src/widgets/itemviews/qtablewidget.cpp b/src/widgets/itemviews/qtablewidget.cpp index 9c2db0e0e4..ed83ef7b85 100644 --- a/src/widgets/itemviews/qtablewidget.cpp +++ b/src/widgets/itemviews/qtablewidget.cpp @@ -2721,5 +2721,6 @@ void QTableWidget::dropEvent(QDropEvent *event) { QT_END_NAMESPACE #include "moc_qtablewidget.cpp" +#include "moc_qtablewidget_p.cpp" #endif // QT_NO_TABLEWIDGET diff --git a/src/widgets/itemviews/qtreewidget.cpp b/src/widgets/itemviews/qtreewidget.cpp index 9e65879f32..74ca7d2827 100644 --- a/src/widgets/itemviews/qtreewidget.cpp +++ b/src/widgets/itemviews/qtreewidget.cpp @@ -3466,5 +3466,6 @@ bool QTreeWidget::event(QEvent *e) QT_END_NAMESPACE #include "moc_qtreewidget.cpp" +#include "moc_qtreewidget_p.cpp" #endif // QT_NO_TREEWIDGET diff --git a/src/widgets/kernel/qboxlayout.cpp b/src/widgets/kernel/qboxlayout.cpp index d167690468..f2e3df5314 100644 --- a/src/widgets/kernel/qboxlayout.cpp +++ b/src/widgets/kernel/qboxlayout.cpp @@ -1354,3 +1354,5 @@ QVBoxLayout::~QVBoxLayout() } QT_END_NAMESPACE + +#include "moc_qboxlayout.cpp" diff --git a/src/widgets/kernel/qdesktopwidget.cpp b/src/widgets/kernel/qdesktopwidget.cpp index 488665ff5f..fceb061867 100644 --- a/src/widgets/kernel/qdesktopwidget.cpp +++ b/src/widgets/kernel/qdesktopwidget.cpp @@ -274,3 +274,4 @@ void QDesktopWidget::resizeEvent(QResizeEvent *) QT_END_NAMESPACE #include "moc_qdesktopwidget.cpp" +#include "moc_qdesktopwidget_p.cpp" diff --git a/src/widgets/kernel/qformlayout.cpp b/src/widgets/kernel/qformlayout.cpp index 2ee7716ac3..9b346a2c50 100644 --- a/src/widgets/kernel/qformlayout.cpp +++ b/src/widgets/kernel/qformlayout.cpp @@ -2114,3 +2114,5 @@ void QFormLayout::dump() const #endif QT_END_NAMESPACE + +#include "moc_qformlayout.cpp" diff --git a/src/widgets/kernel/qgridlayout.cpp b/src/widgets/kernel/qgridlayout.cpp index f3d294bd77..b58e7fdc9e 100644 --- a/src/widgets/kernel/qgridlayout.cpp +++ b/src/widgets/kernel/qgridlayout.cpp @@ -1692,3 +1692,5 @@ void QGridLayout::invalidate() } QT_END_NAMESPACE + +#include "moc_qgridlayout.cpp" diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp index 6c94d81e43..240f525722 100644 --- a/src/widgets/kernel/qlayout.cpp +++ b/src/widgets/kernel/qlayout.cpp @@ -1477,3 +1477,5 @@ QSize QLayout::closestAcceptableSize(const QWidget *widget, const QSize &size) } QT_END_NAMESPACE + +#include "moc_qlayout.cpp" diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index f3c86ea306..5071c56763 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -1349,3 +1349,5 @@ bool QOpenGLWidget::event(QEvent *e) } QT_END_NAMESPACE + +#include "moc_qopenglwidget.cpp" diff --git a/src/widgets/kernel/qshortcut.cpp b/src/widgets/kernel/qshortcut.cpp index 77efaf1632..bf162249d0 100644 --- a/src/widgets/kernel/qshortcut.cpp +++ b/src/widgets/kernel/qshortcut.cpp @@ -658,3 +658,5 @@ bool QShortcut::event(QEvent *e) #endif // QT_NO_SHORTCUT QT_END_NAMESPACE + +#include "moc_qshortcut.cpp" diff --git a/src/widgets/kernel/qsizepolicy.cpp b/src/widgets/kernel/qsizepolicy.cpp index 63024fcf42..66fa350f81 100644 --- a/src/widgets/kernel/qsizepolicy.cpp +++ b/src/widgets/kernel/qsizepolicy.cpp @@ -512,3 +512,5 @@ QDebug operator<<(QDebug dbg, const QSizePolicy &p) #endif QT_END_NAMESPACE + +#include "moc_qsizepolicy.cpp" diff --git a/src/widgets/kernel/qstackedlayout.cpp b/src/widgets/kernel/qstackedlayout.cpp index 05f7f39f0f..006b3e8588 100644 --- a/src/widgets/kernel/qstackedlayout.cpp +++ b/src/widgets/kernel/qstackedlayout.cpp @@ -596,3 +596,5 @@ void QStackedLayout::setStackingMode(StackingMode stackingMode) } QT_END_NAMESPACE + +#include "moc_qstackedlayout.cpp" diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index ec5a68eeef..027bf63a2e 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1892,7 +1892,6 @@ void QWidgetPrivate::deleteTLSysExtra() if (extra->topextra->window) { extra->topextra->window->destroy(); } - setWinId(0); delete extra->topextra->window; extra->topextra->window = 0; @@ -7245,7 +7244,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) if (q->isVisible()) hide_sys(); data.crect = QRect(x, y, w, h); - } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) { + } else if (q->testAttribute(Qt::WA_OutsideWSRange)) { q->setAttribute(Qt::WA_OutsideWSRange, false); needsShow = true; } diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h index cce31e4011..43ca76ac7c 100644 --- a/src/widgets/kernel/qwidget.h +++ b/src/widgets/kernel/qwidget.h @@ -612,43 +612,43 @@ Q_SIGNALS: protected: // Event handlers - bool event(QEvent *) Q_DECL_OVERRIDE; - virtual void mousePressEvent(QMouseEvent *); - virtual void mouseReleaseEvent(QMouseEvent *); - virtual void mouseDoubleClickEvent(QMouseEvent *); - virtual void mouseMoveEvent(QMouseEvent *); + bool event(QEvent *event) Q_DECL_OVERRIDE; + virtual void mousePressEvent(QMouseEvent *event); + virtual void mouseReleaseEvent(QMouseEvent *event); + virtual void mouseDoubleClickEvent(QMouseEvent *event); + virtual void mouseMoveEvent(QMouseEvent *event); #ifndef QT_NO_WHEELEVENT - virtual void wheelEvent(QWheelEvent *); -#endif - virtual void keyPressEvent(QKeyEvent *); - virtual void keyReleaseEvent(QKeyEvent *); - virtual void focusInEvent(QFocusEvent *); - virtual void focusOutEvent(QFocusEvent *); - virtual void enterEvent(QEvent *); - virtual void leaveEvent(QEvent *); - virtual void paintEvent(QPaintEvent *); - virtual void moveEvent(QMoveEvent *); - virtual void resizeEvent(QResizeEvent *); - virtual void closeEvent(QCloseEvent *); + virtual void wheelEvent(QWheelEvent *event); +#endif + virtual void keyPressEvent(QKeyEvent *event); + virtual void keyReleaseEvent(QKeyEvent *event); + virtual void focusInEvent(QFocusEvent *event); + virtual void focusOutEvent(QFocusEvent *event); + virtual void enterEvent(QEvent *event); + virtual void leaveEvent(QEvent *event); + virtual void paintEvent(QPaintEvent *event); + virtual void moveEvent(QMoveEvent *event); + virtual void resizeEvent(QResizeEvent *event); + virtual void closeEvent(QCloseEvent *event); #ifndef QT_NO_CONTEXTMENU - virtual void contextMenuEvent(QContextMenuEvent *); + virtual void contextMenuEvent(QContextMenuEvent *event); #endif #ifndef QT_NO_TABLETEVENT - virtual void tabletEvent(QTabletEvent *); + virtual void tabletEvent(QTabletEvent *event); #endif #ifndef QT_NO_ACTION - virtual void actionEvent(QActionEvent *); + virtual void actionEvent(QActionEvent *event); #endif #ifndef QT_NO_DRAGANDDROP - virtual void dragEnterEvent(QDragEnterEvent *); - virtual void dragMoveEvent(QDragMoveEvent *); - virtual void dragLeaveEvent(QDragLeaveEvent *); - virtual void dropEvent(QDropEvent *); + virtual void dragEnterEvent(QDragEnterEvent *event); + virtual void dragMoveEvent(QDragMoveEvent *event); + virtual void dragLeaveEvent(QDragLeaveEvent *event); + virtual void dropEvent(QDropEvent *event); #endif - virtual void showEvent(QShowEvent *); - virtual void hideEvent(QHideEvent *); + virtual void showEvent(QShowEvent *event); + virtual void hideEvent(QHideEvent *event); virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result); // Misc. protected functions diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index fe5b3cc85d..91af7a4cb0 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -74,7 +74,6 @@ QT_BEGIN_NAMESPACE // Extra QWidget data // - to minimize memory usage for members that are seldom used. // - top-level widgets have extra extra data to reduce cost further -class QWidgetWindow; class QPaintEngine; class QPixmap; class QWidgetBackingStore; @@ -160,7 +159,7 @@ struct QTLWExtra { QWidgetBackingStoreTracker backingStoreTracker; QBackingStore *backingStore; QPainter *sharedPainter; - QWidgetWindow *window; + QWindow *window; QOpenGLContext *shareContext; // Implicit pointers (shared_null). diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 03f62582ff..9025160e5c 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -1631,3 +1631,5 @@ void QWidgetPrivate::repaint_sys(const QRegion &rgn) QT_END_NAMESPACE + +#include "moc_qwidgetbackingstore_p.cpp" diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index def371c36e..c22841dd56 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -1007,3 +1007,5 @@ void QWidgetWindow::updateObjectName() } QT_END_NAMESPACE + +#include "moc_qwidgetwindow_p.cpp" diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp index 462a41ce5d..d7f4b1f989 100644 --- a/src/widgets/kernel/qwindowcontainer.cpp +++ b/src/widgets/kernel/qwindowcontainer.cpp @@ -403,3 +403,5 @@ void QWindowContainer::parentWasLowered(QWidget *parent) } QT_END_NAMESPACE + +#include "moc_qwindowcontainer_p.cpp" diff --git a/src/widgets/statemachine/qbasickeyeventtransition.cpp b/src/widgets/statemachine/qbasickeyeventtransition.cpp index e1b4e262e8..fe2edca613 100644 --- a/src/widgets/statemachine/qbasickeyeventtransition.cpp +++ b/src/widgets/statemachine/qbasickeyeventtransition.cpp @@ -203,4 +203,6 @@ void QBasicKeyEventTransition::onTransition(QEvent *) QT_END_NAMESPACE +#include "moc_qbasickeyeventtransition_p.cpp" + #endif //QT_NO_STATEMACHINE diff --git a/src/widgets/statemachine/qbasicmouseeventtransition.cpp b/src/widgets/statemachine/qbasicmouseeventtransition.cpp index 6ca76ce1b1..39c69b95f5 100644 --- a/src/widgets/statemachine/qbasicmouseeventtransition.cpp +++ b/src/widgets/statemachine/qbasicmouseeventtransition.cpp @@ -208,4 +208,6 @@ void QBasicMouseEventTransition::onTransition(QEvent *) QT_END_NAMESPACE +#include "moc_qbasicmouseeventtransition_p.cpp" + #endif //QT_NO_STATEMACHINE diff --git a/src/widgets/statemachine/qkeyeventtransition.cpp b/src/widgets/statemachine/qkeyeventtransition.cpp index ef5151d1eb..0e9f8458c2 100644 --- a/src/widgets/statemachine/qkeyeventtransition.cpp +++ b/src/widgets/statemachine/qkeyeventtransition.cpp @@ -174,4 +174,6 @@ void QKeyEventTransition::onTransition(QEvent *event) QT_END_NAMESPACE +#include "moc_qkeyeventtransition.cpp" + #endif //QT_NO_STATEMACHINE diff --git a/src/widgets/statemachine/qmouseeventtransition.cpp b/src/widgets/statemachine/qmouseeventtransition.cpp index d287bb23aa..047a9779fe 100644 --- a/src/widgets/statemachine/qmouseeventtransition.cpp +++ b/src/widgets/statemachine/qmouseeventtransition.cpp @@ -202,4 +202,6 @@ void QMouseEventTransition::onTransition(QEvent *event) QT_END_NAMESPACE +#include "moc_qmouseeventtransition.cpp" + #endif //QT_NO_STATEMACHINE diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index 1cd91a26ee..3bab2f5dbe 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -3741,4 +3741,6 @@ QPixmap QFusionStyle::standardPixmap(StandardPixmap standardPixmap, const QStyle QT_END_NAMESPACE +#include "moc_qfusionstyle_p.cpp" + #endif // QT_NO_STYLE_FUSION || QT_PLUGIN diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index 782077fe70..d29ff93382 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -1102,17 +1102,67 @@ static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSiz } #endif -static void qt_drawFocusRingOnPath(CGContextRef cg, NSBezierPath *focusRingPath) +void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius) const { - CGContextSaveGState(cg); - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext - graphicsContextWithGraphicsPort:(CGContextRef)cg flipped:NO]]; - NSSetFocusRingStyle(NSFocusRingOnly); - [focusRingPath setClip]; // Clear clip path to avoid artifacts when rendering the cursor at zero pos - [focusRingPath fill]; - [NSGraphicsContext restoreGraphicsState]; - CGContextRestoreGState(cg); + qreal pixelRatio = p->device()->devicePixelRatioF(); + static const QString keyFormat = QLatin1String("$qt_focusring%1-%2-%3-%4"); + const QString &key = keyFormat.arg(hMargin).arg(vMargin).arg(radius).arg(pixelRatio); + QPixmap focusRingPixmap; + const qreal size = radius * 2 + 5; + + if (!QPixmapCache::find(key, focusRingPixmap)) { + focusRingPixmap = QPixmap((QSize(size, size) + 2 * QSize(hMargin, vMargin)) * pixelRatio); + focusRingPixmap.fill(Qt::transparent); + focusRingPixmap.setDevicePixelRatio(pixelRatio); + { + QMacAutoReleasePool pool; + NSBezierPath *focusRingPath; + if (radius > 0) + focusRingPath = [NSBezierPath bezierPathWithRoundedRect:NSMakeRect(hMargin, vMargin, size, size) + xRadius:radius + yRadius:radius]; + else + focusRingPath = [NSBezierPath bezierPathWithRect:NSMakeRect(hMargin, vMargin, size, size)]; + [NSGraphicsContext saveGraphicsState]; + QMacCGContext gc(&focusRingPixmap); + [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:(CGContextRef)gc + flipped:NO]]; + NSSetFocusRingStyle(NSFocusRingOnly); + [focusRingPath fill]; + [NSGraphicsContext restoreGraphicsState]; + } + QPixmapCache::insert(key, focusRingPixmap); + } + + // Add 2 for the actual ring tickness going inwards + const qreal hCornerSize = 2 + hMargin + radius; + const qreal vCornerSize = 2 + vMargin + radius; + const qreal shCornerSize = hCornerSize * pixelRatio; + const qreal svCornerSize = vCornerSize * pixelRatio; + // top-left corner + p->drawPixmap(QPointF(targetRect.left(), targetRect.top()), focusRingPixmap, + QRectF(0, 0, shCornerSize, svCornerSize)); + // top-right corner + p->drawPixmap(QPointF(targetRect.right() - hCornerSize + 1, targetRect.top()), focusRingPixmap, + QRectF(focusRingPixmap.width() - shCornerSize, 0, shCornerSize, svCornerSize)); + // bottom-left corner + p->drawPixmap(QPointF(targetRect.left(), targetRect.bottom() - vCornerSize + 1), focusRingPixmap, + QRectF(0, focusRingPixmap.height() - svCornerSize, shCornerSize, svCornerSize)); + // bottom-right corner + p->drawPixmap(QPointF(targetRect.right() - hCornerSize + 1, targetRect.bottom() - vCornerSize + 1), focusRingPixmap, + QRect(focusRingPixmap.width() - shCornerSize, focusRingPixmap.height() - svCornerSize, shCornerSize, svCornerSize)); + // top edge + p->drawPixmap(QRectF(targetRect.left() + hCornerSize, targetRect.top(), targetRect.width() - 2 * hCornerSize, vCornerSize), focusRingPixmap, + QRect(shCornerSize, 0, focusRingPixmap.width() - 2 * shCornerSize, svCornerSize)); + // bottom edge + p->drawPixmap(QRectF(targetRect.left() + hCornerSize, targetRect.bottom() - vCornerSize + 1, targetRect.width() - 2 * hCornerSize, vCornerSize), focusRingPixmap, + QRect(shCornerSize, focusRingPixmap.height() - svCornerSize, focusRingPixmap.width() - 2 * shCornerSize, svCornerSize)); + // left edge + p->drawPixmap(QRectF(targetRect.left(), targetRect.top() + vCornerSize, hCornerSize, targetRect.height() - 2 * vCornerSize), focusRingPixmap, + QRect(0, svCornerSize, shCornerSize, focusRingPixmap.width() - 2 * svCornerSize)); + // right edge + p->drawPixmap(QRectF(targetRect.right() - hCornerSize + 1, targetRect.top() + vCornerSize, hCornerSize, targetRect.height() - 2 * vCornerSize), focusRingPixmap, + QRect(focusRingPixmap.width() - shCornerSize, svCornerSize, shCornerSize, focusRingPixmap.width() - 2 * svCornerSize)); } QAquaWidgetSize QMacStylePrivate::effectiveAquaSizeConstrain(const QStyleOption *option, @@ -3924,12 +3974,11 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } } - NSBezierPath *pushButtonFocusRingPath; - if (bdi.kind == kThemeBevelButton) - pushButtonFocusRingPath = [NSBezierPath bezierPathWithRect:NSRectFromCGRect(focusRect)]; - else - pushButtonFocusRingPath = [NSBezierPath bezierPathWithRoundedRect:NSRectFromCGRect(focusRect) xRadius:4 yRadius:4]; - qt_drawFocusRingOnPath(cg, pushButtonFocusRingPath); + const qreal radius = bdi.kind == kThemeBevelButton ? 0 : 4; + const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, btn, w); + const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, btn, w); + const QRect focusTargetRect(focusRect.origin.x, focusRect.origin.y, focusRect.size.width, focusRect.size.height); + d->drawFocusRing(p, focusTargetRect.adjusted(-hMargin, -vMargin, hMargin, vMargin), hMargin, vMargin, radius); } if (hasMenu && (!usingYosemiteOrLater || bdi.kind == kThemeBevelButton)) { @@ -4367,12 +4416,9 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } break; case CE_FocusFrame: { - int xOff = proxy()->pixelMetric(PM_FocusFrameHMargin, opt, w); - int yOff = proxy()->pixelMetric(PM_FocusFrameVMargin, opt, w); - NSRect rect = NSMakeRect(xOff+opt->rect.x(), yOff+opt->rect.y(), opt->rect.width() - 2 * xOff, - opt->rect.height() - 2 * yOff); - NSBezierPath *focusFramePath = [NSBezierPath bezierPathWithRect:rect]; - qt_drawFocusRingOnPath(cg, focusFramePath); + const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, opt, w); + const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, opt, w); + d->drawFocusRing(p, opt->rect, hMargin, vMargin); break; } case CE_MenuItem: case CE_MenuEmptyArea: diff --git a/src/widgets/styles/qmacstyle_mac_p_p.h b/src/widgets/styles/qmacstyle_mac_p_p.h index 53dd2b7a23..31ba8c3464 100644 --- a/src/widgets/styles/qmacstyle_mac_p_p.h +++ b/src/widgets/styles/qmacstyle_mac_p_p.h @@ -218,6 +218,8 @@ public: void drawNSViewInRect(QCocoaWidget widget, NSView *view, const QRect &rect, QPainter *p, bool isQWidget = true, QCocoaDrawRectBlock drawRectBlock = nil) const; void resolveCurrentNSView(QWindow *window); + void drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius = 0) const; + public: mutable QPointer<QObject> pressedButton; mutable QPointer<QObject> defaultButton; diff --git a/src/widgets/styles/qproxystyle.cpp b/src/widgets/styles/qproxystyle.cpp index df152d1f39..182c974729 100644 --- a/src/widgets/styles/qproxystyle.cpp +++ b/src/widgets/styles/qproxystyle.cpp @@ -429,4 +429,6 @@ int QProxyStyle::layoutSpacing(QSizePolicy::ControlType control1, QT_END_NAMESPACE +#include "moc_qproxystyle.cpp" + #endif // QT_NO_STYLE_PROXY diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp index 26bb227e29..103c49496e 100644 --- a/src/widgets/styles/qstyle.cpp +++ b/src/widgets/styles/qstyle.cpp @@ -2424,3 +2424,5 @@ void QStyle::setProxy(QStyle *style) } QT_END_NAMESPACE + +#include "moc_qstyle.cpp" diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h index 0f9c9379f5..0f1259160e 100644 --- a/src/widgets/styles/qstyle.h +++ b/src/widgets/styles/qstyle.h @@ -72,13 +72,13 @@ public: QStyle(); virtual ~QStyle(); - virtual void polish(QWidget *); - virtual void unpolish(QWidget *); + virtual void polish(QWidget *widget); + virtual void unpolish(QWidget *widget); - virtual void polish(QApplication *); - virtual void unpolish(QApplication *); + virtual void polish(QApplication *application); + virtual void unpolish(QApplication *application); - virtual void polish(QPalette &); + virtual void polish(QPalette &palette); virtual QRect itemTextRect(const QFontMetrics &fm, const QRect &r, int flags, bool enabled, diff --git a/src/widgets/styles/qstyleanimation.cpp b/src/widgets/styles/qstyleanimation.cpp index 53af663dcd..67e2ee3225 100644 --- a/src/widgets/styles/qstyleanimation.cpp +++ b/src/widgets/styles/qstyleanimation.cpp @@ -365,4 +365,6 @@ void QScrollbarStyleAnimation::updateCurrentTime(int time) QT_END_NAMESPACE +#include "moc_qstyleanimation_p.cpp" + #endif //QT_NO_ANIMATION diff --git a/src/widgets/styles/qstyleplugin.cpp b/src/widgets/styles/qstyleplugin.cpp index 464cc95827..b29ff0b9a1 100644 --- a/src/widgets/styles/qstyleplugin.cpp +++ b/src/widgets/styles/qstyleplugin.cpp @@ -105,3 +105,5 @@ QStylePlugin::~QStylePlugin() } QT_END_NAMESPACE + +#include "moc_qstyleplugin.cpp" diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index d8af8c5de8..36aa312ce8 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -2403,4 +2403,6 @@ QIcon QWindowsStyle::standardIcon(StandardPixmap standardIcon, const QStyleOptio QT_END_NAMESPACE +#include "moc_qwindowsstyle_p.cpp" + #endif // QT_NO_STYLE_WINDOWS diff --git a/src/widgets/styles/qwindowsstyle_p.h b/src/widgets/styles/qwindowsstyle_p.h index 37b78c9523..f9d174d3c6 100644 --- a/src/widgets/styles/qwindowsstyle_p.h +++ b/src/widgets/styles/qwindowsstyle_p.h @@ -103,7 +103,6 @@ protected: private: Q_DISABLE_COPY(QWindowsStyle) Q_DECLARE_PRIVATE(QWindowsStyle) - void *reserved; }; #endif // QT_NO_STYLE_WINDOWS diff --git a/src/widgets/styles/qwindowsxpstyle_p.h b/src/widgets/styles/qwindowsxpstyle_p.h index a3981ad104..61bb508511 100644 --- a/src/widgets/styles/qwindowsxpstyle_p.h +++ b/src/widgets/styles/qwindowsxpstyle_p.h @@ -99,7 +99,6 @@ private: Q_DISABLE_COPY(QWindowsXPStyle) Q_DECLARE_PRIVATE(QWindowsXPStyle) friend class QStyleFactory; - void *reserved; }; #endif // QT_NO_STYLE_WINDOWSXP diff --git a/src/widgets/util/qcompleter.cpp b/src/widgets/util/qcompleter.cpp index 9f167f5924..083a4a4f27 100644 --- a/src/widgets/util/qcompleter.cpp +++ b/src/widgets/util/qcompleter.cpp @@ -1886,4 +1886,6 @@ QT_END_NAMESPACE #include "moc_qcompleter.cpp" +#include "moc_qcompleter_p.cpp" + #endif // QT_NO_COMPLETER diff --git a/src/widgets/util/qflickgesture.cpp b/src/widgets/util/qflickgesture.cpp index 933db1711b..4f08664784 100644 --- a/src/widgets/util/qflickgesture.cpp +++ b/src/widgets/util/qflickgesture.cpp @@ -715,4 +715,6 @@ void QFlickGestureRecognizer::reset(QGesture *state) QT_END_NAMESPACE +#include "moc_qflickgesture_p.cpp" + #endif // QT_NO_GESTURES diff --git a/src/widgets/util/qscroller.cpp b/src/widgets/util/qscroller.cpp index 02e3c2b82a..2e48208402 100644 --- a/src/widgets/util/qscroller.cpp +++ b/src/widgets/util/qscroller.cpp @@ -2063,3 +2063,6 @@ qreal QScrollerPrivate::nextSnapPos(qreal p, int dir, Qt::Orientation orientatio */ QT_END_NAMESPACE + +#include "moc_qscroller.cpp" +#include "moc_qscroller_p.cpp" diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp index 59f7fae28e..3606b7c773 100644 --- a/src/widgets/util/qsystemtrayicon.cpp +++ b/src/widgets/util/qsystemtrayicon.cpp @@ -772,3 +772,4 @@ QT_END_NAMESPACE #endif // QT_NO_SYSTEMTRAYICON #include "moc_qsystemtrayicon.cpp" +#include "moc_qsystemtrayicon_p.cpp" diff --git a/src/widgets/util/qundogroup.cpp b/src/widgets/util/qundogroup.cpp index c8623f44fe..ec4fc2788a 100644 --- a/src/widgets/util/qundogroup.cpp +++ b/src/widgets/util/qundogroup.cpp @@ -501,4 +501,6 @@ QAction *QUndoGroup::createRedoAction(QObject *parent, const QString &prefix) co QT_END_NAMESPACE +#include "moc_qundogroup.cpp" + #endif // QT_NO_UNDOGROUP diff --git a/src/widgets/util/qundostack.cpp b/src/widgets/util/qundostack.cpp index 6f733f99d5..7f6a56e0ec 100644 --- a/src/widgets/util/qundostack.cpp +++ b/src/widgets/util/qundostack.cpp @@ -1174,4 +1174,7 @@ bool QUndoStack::isActive() const QT_END_NAMESPACE +#include "moc_qundostack.cpp" +#include "moc_qundostack_p.cpp" + #endif // QT_NO_UNDOSTACK diff --git a/src/widgets/util/qundoview.cpp b/src/widgets/util/qundoview.cpp index 9a89c42a3e..93c1778ea2 100644 --- a/src/widgets/util/qundoview.cpp +++ b/src/widgets/util/qundoview.cpp @@ -472,5 +472,6 @@ QIcon QUndoView::cleanIcon() const QT_END_NAMESPACE #include "qundoview.moc" +#include "moc_qundoview.cpp" #endif // QT_NO_UNDOVIEW diff --git a/src/widgets/widgets/qabstractbutton.cpp b/src/widgets/widgets/qabstractbutton.cpp index 9133664d77..44123d4dda 100644 --- a/src/widgets/widgets/qabstractbutton.cpp +++ b/src/widgets/widgets/qabstractbutton.cpp @@ -37,7 +37,9 @@ ** ****************************************************************************/ -#include "qabstractbutton.h" +#include "private/qabstractbutton_p.h" + +#include "private/qbuttongroup_p.h" #include "qabstractitemview.h" #include "qbuttongroup.h" #include "qabstractbutton_p.h" @@ -177,137 +179,6 @@ QAbstractButtonPrivate::QAbstractButtonPrivate(QSizePolicy::ControlType type) controlType(type) {} -#ifndef QT_NO_BUTTONGROUP - -class QButtonGroupPrivate: public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QButtonGroup) - -public: - QButtonGroupPrivate():exclusive(true){} - QList<QAbstractButton *> buttonList; - QPointer<QAbstractButton> checkedButton; - void detectCheckedButton(); - void notifyChecked(QAbstractButton *button); - bool exclusive; - QHash<QAbstractButton*, int> mapping; -}; - -QButtonGroup::QButtonGroup(QObject *parent) - : QObject(*new QButtonGroupPrivate, parent) -{ -} - -QButtonGroup::~QButtonGroup() -{ - Q_D(QButtonGroup); - for (int i = 0; i < d->buttonList.count(); ++i) - d->buttonList.at(i)->d_func()->group = 0; -} - - -bool QButtonGroup::exclusive() const -{ - Q_D(const QButtonGroup); - return d->exclusive; -} - -void QButtonGroup::setExclusive(bool exclusive) -{ - Q_D(QButtonGroup); - d->exclusive = exclusive; -} - - -void QButtonGroup::addButton(QAbstractButton *button, int id) -{ - Q_D(QButtonGroup); - if (QButtonGroup *previous = button->d_func()->group) - previous->removeButton(button); - button->d_func()->group = this; - d->buttonList.append(button); - if (id == -1) { - const QHash<QAbstractButton*, int>::const_iterator it - = std::min_element(d->mapping.cbegin(), d->mapping.cend()); - if (it == d->mapping.cend()) - d->mapping[button] = -2; - else - d->mapping[button] = *it - 1; - } else { - d->mapping[button] = id; - } - - if (d->exclusive && button->isChecked()) - button->d_func()->notifyChecked(); -} - -void QButtonGroup::removeButton(QAbstractButton *button) -{ - Q_D(QButtonGroup); - if (d->checkedButton == button) { - d->detectCheckedButton(); - } - if (button->d_func()->group == this) { - button->d_func()->group = 0; - d->buttonList.removeAll(button); - d->mapping.remove(button); - } -} - -QList<QAbstractButton*> QButtonGroup::buttons() const -{ - Q_D(const QButtonGroup); - return d->buttonList; -} - -QAbstractButton *QButtonGroup::checkedButton() const -{ - Q_D(const QButtonGroup); - return d->checkedButton; -} - -QAbstractButton *QButtonGroup::button(int id) const -{ - Q_D(const QButtonGroup); - return d->mapping.key(id); -} - -void QButtonGroup::setId(QAbstractButton *button, int id) -{ - Q_D(QButtonGroup); - if (button && id != -1) - d->mapping[button] = id; -} - -int QButtonGroup::id(QAbstractButton *button) const -{ - Q_D(const QButtonGroup); - return d->mapping.value(button, -1); -} - -int QButtonGroup::checkedId() const -{ - Q_D(const QButtonGroup); - return d->mapping.value(d->checkedButton, -1); -} - -// detect a checked button other than the current one -void QButtonGroupPrivate::detectCheckedButton() -{ - QAbstractButton *previous = checkedButton; - checkedButton = 0; - if (exclusive) - return; - for (int i = 0; i < buttonList.count(); i++) { - if (buttonList.at(i) != previous && buttonList.at(i)->isChecked()) { - checkedButton = buttonList.at(i); - return; - } - } -} - -#endif // QT_NO_BUTTONGROUP - QList<QAbstractButton *>QAbstractButtonPrivate::queryButtonList() const { #ifndef QT_NO_BUTTONGROUP @@ -1419,3 +1290,5 @@ void QAbstractButton::setIconSize(const QSize &size) QT_END_NAMESPACE + +#include "moc_qabstractbutton.cpp" diff --git a/src/widgets/widgets/qabstractbutton_p.h b/src/widgets/widgets/qabstractbutton_p.h index 416a9c4c83..f65a0527fc 100644 --- a/src/widgets/widgets/qabstractbutton_p.h +++ b/src/widgets/widgets/qabstractbutton_p.h @@ -51,6 +51,8 @@ // We mean it. // +#include "qabstractbutton.h" + #include "QtCore/qbasictimer.h" #include "private/qwidget_p.h" diff --git a/src/widgets/widgets/qabstractslider.cpp b/src/widgets/widgets/qabstractslider.cpp index 13e7a6e5cf..8cd35495e9 100644 --- a/src/widgets/widgets/qabstractslider.cpp +++ b/src/widgets/widgets/qabstractslider.cpp @@ -962,3 +962,5 @@ void QAbstractSliderPrivate::itemviewChangeSingleStep(int step) } QT_END_NAMESPACE + +#include "moc_qabstractslider.cpp" diff --git a/src/widgets/widgets/qbuttongroup.cpp b/src/widgets/widgets/qbuttongroup.cpp index 7cc260a6f0..ef73fd1b67 100644 --- a/src/widgets/widgets/qbuttongroup.cpp +++ b/src/widgets/widgets/qbuttongroup.cpp @@ -37,7 +37,28 @@ ** ****************************************************************************/ +#include "private/qbuttongroup_p.h" +#ifndef QT_NO_BUTTONGROUP + +#include "private/qabstractbutton_p.h" + +QT_BEGIN_NAMESPACE + +// detect a checked button other than the current one +void QButtonGroupPrivate::detectCheckedButton() +{ + QAbstractButton *previous = checkedButton; + checkedButton = 0; + if (exclusive) + return; + for (int i = 0; i < buttonList.count(); i++) { + if (buttonList.at(i) != previous && buttonList.at(i)->isChecked()) { + checkedButton = buttonList.at(i); + return; + } + } +} /*! \class QButtonGroup @@ -84,18 +105,24 @@ */ /*! - \fn QButtonGroup::QButtonGroup(QObject *parent) - Constructs a new, empty button group with the given \a parent. \sa addButton(), setExclusive() */ +QButtonGroup::QButtonGroup(QObject *parent) + : QObject(*new QButtonGroupPrivate, parent) +{ +} /*! - \fn QButtonGroup::~QButtonGroup() - Destroys the button group. */ +QButtonGroup::~QButtonGroup() +{ + Q_D(QButtonGroup); + for (int i = 0; i < d->buttonList.count(); ++i) + d->buttonList.at(i)->d_func()->group = 0; +} /*! \property QButtonGroup::exclusive @@ -111,6 +138,19 @@ By default, this property is \c true. */ +bool QButtonGroup::exclusive() const +{ + Q_D(const QButtonGroup); + return d->exclusive; +} + +void QButtonGroup::setExclusive(bool exclusive) +{ + Q_D(QButtonGroup); + d->exclusive = exclusive; +} + + /*! \fn void QButtonGroup::buttonClicked(QAbstractButton *button) @@ -193,8 +233,6 @@ /*! - \fn void QButtonGroup::addButton(QAbstractButton *button, int id = -1); - Adds the given \a button to the button group. If \a id is -1, an id will be assigned to the button. Automatically assigned ids are guaranteed to be negative, @@ -203,42 +241,82 @@ \sa removeButton(), buttons() */ +void QButtonGroup::addButton(QAbstractButton *button, int id) +{ + Q_D(QButtonGroup); + if (QButtonGroup *previous = button->d_func()->group) + previous->removeButton(button); + button->d_func()->group = this; + d->buttonList.append(button); + if (id == -1) { + const QHash<QAbstractButton*, int>::const_iterator it + = std::min_element(d->mapping.cbegin(), d->mapping.cend()); + if (it == d->mapping.cend()) + d->mapping[button] = -2; + else + d->mapping[button] = *it - 1; + } else { + d->mapping[button] = id; + } + + if (d->exclusive && button->isChecked()) + button->d_func()->notifyChecked(); +} /*! - \fn void QButtonGroup::removeButton(QAbstractButton *button); - Removes the given \a button from the button group. \sa addButton(), buttons() */ +void QButtonGroup::removeButton(QAbstractButton *button) +{ + Q_D(QButtonGroup); + if (d->checkedButton == button) { + d->detectCheckedButton(); + } + if (button->d_func()->group == this) { + button->d_func()->group = 0; + d->buttonList.removeAll(button); + d->mapping.remove(button); + } +} /*! - \fn QList<QAbstractButton*> QButtonGroup::buttons() const - Returns the button group's list of buttons. This may be empty. \sa addButton(), removeButton() */ +QList<QAbstractButton*> QButtonGroup::buttons() const +{ + Q_D(const QButtonGroup); + return d->buttonList; +} /*! - \fn QAbstractButton *QButtonGroup::checkedButton() const; - Returns the button group's checked button, or 0 if no buttons are checked. \sa buttonClicked() */ +QAbstractButton *QButtonGroup::checkedButton() const +{ + Q_D(const QButtonGroup); + return d->checkedButton; +} /*! - \fn QAbstractButton *QButtonGroup::button(int id) const; \since 4.1 Returns the button with the specified \a id, or 0 if no such button exists. */ +QAbstractButton *QButtonGroup::button(int id) const +{ + Q_D(const QButtonGroup); + return d->mapping.key(id); +} /*! - \fn void QButtonGroup::setId(QAbstractButton *button, int id) \since 4.1 Sets the \a id for the specified \a button. Note that \a id cannot @@ -246,9 +324,14 @@ \sa id() */ +void QButtonGroup::setId(QAbstractButton *button, int id) +{ + Q_D(QButtonGroup); + if (button && id != -1) + d->mapping[button] = id; +} /*! - \fn int QButtonGroup::id(QAbstractButton *button) const; \since 4.1 Returns the id for the specified \a button, or -1 if no such button @@ -257,13 +340,27 @@ \sa setId() */ +int QButtonGroup::id(QAbstractButton *button) const +{ + Q_D(const QButtonGroup); + return d->mapping.value(button, -1); +} /*! - \fn int QButtonGroup::checkedId() const; \since 4.1 Returns the id of the checkedButton(), or -1 if no button is checked. \sa setId() */ +int QButtonGroup::checkedId() const +{ + Q_D(const QButtonGroup); + return d->mapping.value(d->checkedButton, -1); +} + +QT_END_NAMESPACE + +#include "moc_qbuttongroup.cpp" +#endif // QT_NO_BUTTONGROUP diff --git a/src/widgets/widgets/qbuttongroup_p.h b/src/widgets/widgets/qbuttongroup_p.h new file mode 100644 index 0000000000..01c0367876 --- /dev/null +++ b/src/widgets/widgets/qbuttongroup_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWidgets module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBUTTONGROUP_P_H +#define QBUTTONGROUP_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 <QtWidgets/qbuttongroup.h> + +#ifndef QT_NO_BUTTONGROUP + +#include <QtCore/private/qobject_p.h> + +#include <QtCore/qlist.h> +#include <QtCore/qpointer.h> +#include <QtCore/qhash.h> + +QT_BEGIN_NAMESPACE + +class QButtonGroupPrivate: public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QButtonGroup) + +public: + QButtonGroupPrivate() : exclusive(true) {} + + QList<QAbstractButton *> buttonList; + QPointer<QAbstractButton> checkedButton; + void detectCheckedButton(); + void notifyChecked(QAbstractButton *button); + + bool exclusive; + QHash<QAbstractButton*, int> mapping; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_BUTTONGROUP + +#endif // QBUTTONGROUP_P_H diff --git a/src/widgets/widgets/qcheckbox.cpp b/src/widgets/widgets/qcheckbox.cpp index ad2d019c4a..19369d6cb1 100644 --- a/src/widgets/widgets/qcheckbox.cpp +++ b/src/widgets/widgets/qcheckbox.cpp @@ -390,3 +390,5 @@ bool QCheckBox::event(QEvent *e) QT_END_NAMESPACE + +#include "moc_qcheckbox.cpp" diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 1cf7591302..08c8117e0b 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -3440,5 +3440,6 @@ void QComboBox::setModelColumn(int visibleColumn) QT_END_NAMESPACE #include "moc_qcombobox.cpp" +#include "moc_qcombobox_p.cpp" #endif // QT_NO_COMBOBOX diff --git a/src/widgets/widgets/qcommandlinkbutton.cpp b/src/widgets/widgets/qcommandlinkbutton.cpp index 4d43c999bf..2ec8b1c41a 100644 --- a/src/widgets/widgets/qcommandlinkbutton.cpp +++ b/src/widgets/widgets/qcommandlinkbutton.cpp @@ -413,3 +413,4 @@ QString QCommandLinkButton::description() const QT_END_NAMESPACE +#include "moc_qcommandlinkbutton.cpp" diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp index c3f9198598..f72dc088da 100644 --- a/src/widgets/widgets/qdatetimeedit.cpp +++ b/src/widgets/widgets/qdatetimeedit.cpp @@ -2692,5 +2692,6 @@ void QCalendarPopup::hideEvent(QHideEvent *) QT_END_NAMESPACE #include "moc_qdatetimeedit.cpp" +#include "moc_qdatetimeedit_p.cpp" #endif // QT_NO_DATETIMEEDIT diff --git a/src/widgets/widgets/qdial.cpp b/src/widgets/widgets/qdial.cpp index 40c7e98726..cee39e2ae3 100644 --- a/src/widgets/widgets/qdial.cpp +++ b/src/widgets/widgets/qdial.cpp @@ -487,4 +487,6 @@ bool QDial::event(QEvent *e) QT_END_NAMESPACE +#include "moc_qdial.cpp" + #endif // QT_NO_DIAL diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index 03faca157f..293a04ef88 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -1682,5 +1682,6 @@ QT_END_NAMESPACE #include "qdockwidget.moc" #include "moc_qdockwidget.cpp" +#include "moc_qdockwidget_p.cpp" #endif // QT_NO_DOCKWIDGET diff --git a/src/widgets/widgets/qfocusframe.cpp b/src/widgets/widgets/qfocusframe.cpp index 6704631afc..8b8f4db86e 100644 --- a/src/widgets/widgets/qfocusframe.cpp +++ b/src/widgets/widgets/qfocusframe.cpp @@ -339,3 +339,5 @@ bool QFocusFrame::event(QEvent *e) } QT_END_NAMESPACE + +#include "moc_qfocusframe.cpp" diff --git a/src/widgets/widgets/qframe.cpp b/src/widgets/widgets/qframe.cpp index 96a2e76713..1661c5c881 100644 --- a/src/widgets/widgets/qframe.cpp +++ b/src/widgets/widgets/qframe.cpp @@ -555,3 +555,5 @@ bool QFrame::event(QEvent *e) } QT_END_NAMESPACE + +#include "moc_qframe.cpp" diff --git a/src/widgets/widgets/qkeysequenceedit.cpp b/src/widgets/widgets/qkeysequenceedit.cpp index a663c4f853..f8a3be366e 100644 --- a/src/widgets/widgets/qkeysequenceedit.cpp +++ b/src/widgets/widgets/qkeysequenceedit.cpp @@ -324,3 +324,5 @@ void QKeySequenceEdit::timerEvent(QTimerEvent *e) #endif // QT_NO_KEYSEQUENCEEDIT QT_END_NAMESPACE + +#include "moc_qkeysequenceedit.cpp" diff --git a/src/widgets/widgets/qlcdnumber.cpp b/src/widgets/widgets/qlcdnumber.cpp index cc1fc20379..543a7aee11 100644 --- a/src/widgets/widgets/qlcdnumber.cpp +++ b/src/widgets/widgets/qlcdnumber.cpp @@ -1222,4 +1222,6 @@ bool QLCDNumber::event(QEvent *e) QT_END_NAMESPACE +#include "moc_qlcdnumber.cpp" + #endif // QT_NO_LCDNUMBER diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index b646e82209..b852b8991c 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -553,4 +553,6 @@ int QLineEditPrivate::effectiveRightTextMargin() const QT_END_NAMESPACE +#include "moc_qlineedit_p.cpp" + #endif diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp index 4ee22dc235..f86244172d 100644 --- a/src/widgets/widgets/qmainwindow.cpp +++ b/src/widgets/widgets/qmainwindow.cpp @@ -1746,4 +1746,6 @@ QMenu *QMainWindow::createPopupMenu() QT_END_NAMESPACE +#include "moc_qmainwindow.cpp" + #endif // QT_NO_MAINWINDOW diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index 99c32e9acc..6c05887705 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -2604,4 +2604,6 @@ void QMainWindowLayout::timerEvent(QTimerEvent *e) QT_END_NAMESPACE +#include "moc_qmainwindowlayout_p.cpp" + #endif // QT_NO_MAINWINDOW diff --git a/src/widgets/widgets/qprogressbar.cpp b/src/widgets/widgets/qprogressbar.cpp index 2897929a14..1ba0d78622 100644 --- a/src/widgets/widgets/qprogressbar.cpp +++ b/src/widgets/widgets/qprogressbar.cpp @@ -629,4 +629,6 @@ QString QProgressBar::format() const QT_END_NAMESPACE +#include "moc_qprogressbar.cpp" + #endif // QT_NO_PROGRESSBAR diff --git a/src/widgets/widgets/qradiobutton.cpp b/src/widgets/widgets/qradiobutton.cpp index 125182f79f..55a584078a 100644 --- a/src/widgets/widgets/qradiobutton.cpp +++ b/src/widgets/widgets/qradiobutton.cpp @@ -269,3 +269,5 @@ bool QRadioButton::event(QEvent *e) QT_END_NAMESPACE + +#include "moc_qradiobutton.cpp" diff --git a/src/widgets/widgets/qrubberband.cpp b/src/widgets/widgets/qrubberband.cpp index 048817d07b..13aa66dec7 100644 --- a/src/widgets/widgets/qrubberband.cpp +++ b/src/widgets/widgets/qrubberband.cpp @@ -333,4 +333,6 @@ bool QRubberBand::event(QEvent *e) QT_END_NAMESPACE +#include "moc_qrubberband.cpp" + #endif // QT_NO_RUBBERBAND diff --git a/src/widgets/widgets/qscrollarea.cpp b/src/widgets/widgets/qscrollarea.cpp index bd07040509..0868dcbd69 100644 --- a/src/widgets/widgets/qscrollarea.cpp +++ b/src/widgets/widgets/qscrollarea.cpp @@ -538,4 +538,6 @@ Qt::Alignment QScrollArea::alignment() const QT_END_NAMESPACE +#include "moc_qscrollarea.cpp" + #endif // QT_NO_SCROLLAREA diff --git a/src/widgets/widgets/qscrollbar.cpp b/src/widgets/widgets/qscrollbar.cpp index 7399601c2e..7dd41f6a0c 100644 --- a/src/widgets/widgets/qscrollbar.cpp +++ b/src/widgets/widgets/qscrollbar.cpp @@ -744,4 +744,6 @@ Q_WIDGETS_EXPORT QStyleOptionSlider qt_qscrollbarStyleOption(QScrollBar *scrollb QT_END_NAMESPACE +#include "moc_qscrollbar.cpp" + #endif // QT_NO_SCROLLBAR diff --git a/src/widgets/widgets/qslider.cpp b/src/widgets/widgets/qslider.cpp index bf27b19940..7b675fccbd 100644 --- a/src/widgets/widgets/qslider.cpp +++ b/src/widgets/widgets/qslider.cpp @@ -559,3 +559,5 @@ Q_WIDGETS_EXPORT QStyleOptionSlider qt_qsliderStyleOption(QSlider *slider) #endif QT_END_NAMESPACE + +#include "moc_qslider.cpp" diff --git a/src/widgets/widgets/qspinbox.cpp b/src/widgets/widgets/qspinbox.cpp index 68b405cc5e..a5c096c3a8 100644 --- a/src/widgets/widgets/qspinbox.cpp +++ b/src/widgets/widgets/qspinbox.cpp @@ -1328,4 +1328,6 @@ bool QSpinBox::event(QEvent *event) QT_END_NAMESPACE +#include "moc_qspinbox.cpp" + #endif // QT_NO_SPINBOX diff --git a/src/widgets/widgets/qsplashscreen.cpp b/src/widgets/widgets/qsplashscreen.cpp index b379e01b0a..4ad2b83582 100644 --- a/src/widgets/widgets/qsplashscreen.cpp +++ b/src/widgets/widgets/qsplashscreen.cpp @@ -358,4 +358,6 @@ bool QSplashScreen::event(QEvent *e) QT_END_NAMESPACE +#include "moc_qsplashscreen.cpp" + #endif //QT_NO_SPLASHSCREEN diff --git a/src/widgets/widgets/qsplitter.cpp b/src/widgets/widgets/qsplitter.cpp index 9ebd232bef..e3ca6b0a79 100644 --- a/src/widgets/widgets/qsplitter.cpp +++ b/src/widgets/widgets/qsplitter.cpp @@ -1739,4 +1739,6 @@ QTextStream& operator>>(QTextStream& ts, QSplitter& splitter) QT_END_NAMESPACE +#include "moc_qsplitter.cpp" + #endif // QT_NO_SPLITTER diff --git a/src/widgets/widgets/qstackedwidget.cpp b/src/widgets/widgets/qstackedwidget.cpp index 097f98fd71..38ce182fbf 100644 --- a/src/widgets/widgets/qstackedwidget.cpp +++ b/src/widgets/widgets/qstackedwidget.cpp @@ -293,4 +293,6 @@ bool QStackedWidget::event(QEvent *e) QT_END_NAMESPACE +#include "moc_qstackedwidget.cpp" + #endif // QT_NO_STACKEDWIDGET diff --git a/src/widgets/widgets/qstatusbar.cpp b/src/widgets/widgets/qstatusbar.cpp index 2e1cd29839..7de1d92acf 100644 --- a/src/widgets/widgets/qstatusbar.cpp +++ b/src/widgets/widgets/qstatusbar.cpp @@ -789,4 +789,6 @@ bool QStatusBar::event(QEvent *e) QT_END_NAMESPACE +#include "moc_qstatusbar.cpp" + #endif diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp index ba3fc2fcd7..f56830c14b 100644 --- a/src/widgets/widgets/qtabbar.cpp +++ b/src/widgets/widgets/qtabbar.cpp @@ -2583,4 +2583,4 @@ QT_END_NAMESPACE #endif // QT_NO_TABBAR - +#include "moc_qtabbar_p.cpp" diff --git a/src/widgets/widgets/qtoolbarextension.cpp b/src/widgets/widgets/qtoolbarextension.cpp index 71061c8102..267e220b8f 100644 --- a/src/widgets/widgets/qtoolbarextension.cpp +++ b/src/widgets/widgets/qtoolbarextension.cpp @@ -87,4 +87,6 @@ QSize QToolBarExtension::sizeHint() const QT_END_NAMESPACE +#include "moc_qtoolbarextension_p.cpp" + #endif // QT_NO_TOOLBUTTON diff --git a/src/widgets/widgets/qtoolbarextension_p.h b/src/widgets/widgets/qtoolbarextension_p.h index e8725d77b8..ea159ce986 100644 --- a/src/widgets/widgets/qtoolbarextension_p.h +++ b/src/widgets/widgets/qtoolbarextension_p.h @@ -60,7 +60,6 @@ QT_BEGIN_NAMESPACE class Q_AUTOTEST_EXPORT QToolBarExtension : public QToolButton { Q_OBJECT - Qt::Orientation orientation; public: explicit QToolBarExtension(QWidget *parent); diff --git a/src/widgets/widgets/qtoolbarlayout.cpp b/src/widgets/widgets/qtoolbarlayout.cpp index 2d7ab68dde..79174bdbff 100644 --- a/src/widgets/widgets/qtoolbarlayout.cpp +++ b/src/widgets/widgets/qtoolbarlayout.cpp @@ -748,4 +748,6 @@ QToolBarItem *QToolBarLayout::createItem(QAction *action) QT_END_NAMESPACE +#include "moc_qtoolbarlayout_p.cpp" + #endif // QT_NO_TOOLBAR diff --git a/src/widgets/widgets/qtoolbarseparator.cpp b/src/widgets/widgets/qtoolbarseparator.cpp index 57997556a5..c99a8bcc4c 100644 --- a/src/widgets/widgets/qtoolbarseparator.cpp +++ b/src/widgets/widgets/qtoolbarseparator.cpp @@ -86,4 +86,6 @@ void QToolBarSeparator::paintEvent(QPaintEvent *) QT_END_NAMESPACE +#include "moc_qtoolbarseparator_p.cpp" + #endif // QT_NO_TOOLBAR diff --git a/src/widgets/widgets/qwidgetanimator.cpp b/src/widgets/widgets/qwidgetanimator.cpp index edf0b32ba0..d46d65546c 100644 --- a/src/widgets/widgets/qwidgetanimator.cpp +++ b/src/widgets/widgets/qwidgetanimator.cpp @@ -120,3 +120,5 @@ bool QWidgetAnimator::animating() const } QT_END_NAMESPACE + +#include "moc_qwidgetanimator_p.cpp" diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp index f9674668ec..a77794df8a 100644 --- a/src/widgets/widgets/qwidgetlinecontrol.cpp +++ b/src/widgets/widgets/qwidgetlinecontrol.cpp @@ -1924,4 +1924,6 @@ bool QWidgetLineControl::isRedoAvailable() const QT_END_NAMESPACE +#include "moc_qwidgetlinecontrol_p.cpp" + #endif diff --git a/src/widgets/widgets/qwidgetresizehandler.cpp b/src/widgets/widgets/qwidgetresizehandler.cpp index 11bfc38b0d..2a7b1eeecc 100644 --- a/src/widgets/widgets/qwidgetresizehandler.cpp +++ b/src/widgets/widgets/qwidgetresizehandler.cpp @@ -541,4 +541,6 @@ void QWidgetResizeHandler::doMove() QT_END_NAMESPACE +#include "moc_qwidgetresizehandler_p.cpp" + #endif //QT_NO_RESIZEHANDLER diff --git a/src/widgets/widgets/widgets.pri b/src/widgets/widgets/widgets.pri index c31a7f7682..784055ed62 100644 --- a/src/widgets/widgets/widgets.pri +++ b/src/widgets/widgets/widgets.pri @@ -2,6 +2,7 @@ HEADERS += \ widgets/qbuttongroup.h \ + widgets/qbuttongroup_p.h \ widgets/qabstractbutton.h \ widgets/qabstractbutton_p.h \ widgets/qabstractslider.h \ @@ -84,6 +85,7 @@ HEADERS += \ widgets/qplaintextedit_p.h SOURCES += \ + widgets/qbuttongroup.cpp \ widgets/qabstractbutton.cpp \ widgets/qabstractslider.cpp \ widgets/qabstractspinbox.cpp \ |