Merge "Merge remote-tracking branch 'origin/5.10' into 5.11" into refs/staging/5.11

bb10
Liang Qi 2018-02-15 21:19:50 +00:00 committed by The Qt Project
commit 1ef03f69e8
52 changed files with 611 additions and 101 deletions

View File

@ -111,6 +111,7 @@ void RasterWindow::renderNow()
painter.fillRect(0, 0, width(), height(), Qt::white);
render(&painter);
painter.end();
m_backingStore->endPaint();
m_backingStore->flush(rect);

View File

@ -52,8 +52,15 @@
#include <QFileDialog>
#include <QTextStream>
#include <QMessageBox>
#if defined(QT_PRINTSUPPORT_LIB)
#include <QtPrintSupport/qtprintsupportglobal.h>
#if QT_CONFIG(printer)
#if QT_CONFIG(printdialog)
#include <QPrintDialog>
#endif // QT_CONFIG(printdialog)
#include <QPrinter>
#endif // QT_CONFIG(printer)
#endif // QT_PRINTSUPPORT_LIB
#include <QFont>
#include <QFontDialog>
@ -136,11 +143,15 @@ void Notepad::on_actionSave_as_triggered()
void Notepad::on_actionPrint_triggered()
{
#if QT_CONFIG(printer)
QPrinter printDev;
#if QT_CONFIG(printdialog)
QPrintDialog dialog(&printDev, this);
if (dialog.exec() == QDialog::Rejected)
return;
#endif // QT_CONFIG(printdialog)
ui->textEdit->print(&printDev);
#endif // QT_CONFIG(printer)
}
void Notepad::on_actionExit_triggered()

View File

@ -1,7 +1,7 @@
TEMPLATE = app
TARGET = notepad
QT += printsupport
qtHaveModule(printsupport): QT += printsupport
requires(qtConfig(fontdialog))
SOURCES += \

View File

@ -58,3 +58,10 @@ QMAKE_XCODE_LIBRARY_SUFFIX_SETTING = QT_LIBRARY_SUFFIX
xcode_copy_phase_strip_setting.name = COPY_PHASE_STRIP
xcode_copy_phase_strip_setting.value = NO
QMAKE_MAC_XCODE_SETTINGS += xcode_copy_phase_strip_setting
xcode_product_bundle_identifier_setting.name = PRODUCT_BUNDLE_IDENTIFIER
xcode_product_bundle_identifier_setting.value = $$QMAKE_TARGET_BUNDLE_PREFIX
isEmpty(xcode_product_bundle_identifier_setting.value): \
xcode_product_bundle_identifier_setting.value = "com.yourcompany"
xcode_product_bundle_identifier_setting.value = "$${xcode_product_bundle_identifier_setting.value}.${PRODUCT_NAME:rfc1034identifier}"
QMAKE_MAC_XCODE_SETTINGS += xcode_product_bundle_identifier_setting

View File

@ -274,7 +274,7 @@ load(qt_targets)
else: \
QMAKE_PKGCONFIG_LIBDIR = $$[QT_INSTALL_LIBS/raw]
QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_HEADERS/raw]
QMAKE_PKGCONFIG_CFLAGS = -I${includedir}/$$MODULE_INCNAME
QMAKE_PKGCONFIG_CFLAGS = -D$$MODULE_DEFINE -I${includedir}/$$MODULE_INCNAME
QMAKE_PKGCONFIG_NAME = $$replace(TARGET, ^Qt, "Qt$$QT_MAJOR_VERSION ")
QMAKE_PKGCONFIG_FILE = $$replace(TARGET, ^Qt, Qt$$QT_MAJOR_VERSION)
for(i, MODULE_DEPENDS): \

View File

@ -10,6 +10,8 @@
load(device_config)
include(../common/gcc-base.conf)
include(../common/g++-base.conf)
include(../common/angle.conf)
include(../common/windows-vulkan.conf)
# modifications to gcc-base.conf and g++-base.conf
@ -31,8 +33,6 @@ QMAKE_CFLAGS += -fno-keep-inline-dllexport
QMAKE_CFLAGS_WARN_ON += -Wextra
QMAKE_CFLAGS_SSE2 += -mstackrealign
QMAKE_CFLAGS_AESNI = -maes
QMAKE_CFLAGS_SHANI = -msha
QMAKE_CXX = $${CROSS_COMPILE}g++
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
@ -86,8 +86,4 @@ QMAKE_STRIPFLAGS_LIB += --strip-unneeded
QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy
QMAKE_NM = $${CROSS_COMPILE}nm -P
include(../common/angle.conf)
include(../common/windows-vulkan.conf)
include(../common/gcc-base.conf)
load(qt_config)

View File

@ -58,7 +58,4 @@ QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG
QMAKE_LIB = xilib /NOLOGO
include(../common/angle.conf)
include(../common/windows-vulkan.conf)
load(qt_config)

View File

@ -6,7 +6,7 @@
"Description": "The Independent JPEG Group's JPEG software",
"Homepage": "http://libjpeg-turbo.virtualgl.org/",
"Version": "1.5.2",
"Version": "1.5.3",
"License": "Independent JPEG Group License",
"LicenseId": "IJG",
"LicenseFile": "LICENSE",

View File

@ -1,3 +1,47 @@
1.5.3
=====
### Significant changes relative to 1.5.2:
1. Fixed a NullPointerException in the TurboJPEG Java wrapper that occurred
when using the YUVImage constructor that creates an instance backed by separate
image planes and allocates memory for the image planes.
2. Fixed an issue whereby the Java version of TJUnitTest would fail when
testing BufferedImage encoding/decoding on big endian systems.
3. Fixed a segfault in djpeg that would occur if an output format other than
PPM/PGM was selected along with the `-crop` option. The `-crop` option now
works with the GIF and Targa formats as well (unfortunately, it cannot be made
to work with the BMP and RLE formats due to the fact that those output engines
write scanlines in bottom-up order.) djpeg will now exit gracefully if an
output format other than PPM/PGM, GIF, or Targa is selected along with the
`-crop` option.
4. Fixed an issue whereby `jpeg_skip_scanlines()` would segfault if color
quantization was enabled.
5. TJBench (both C and Java versions) will now display usage information if any
command-line argument is unrecognized. This prevents the program from silently
ignoring typos.
6. Fixed an access violation in tjbench.exe (Windows) that occurred when the
program was used to decompress an existing JPEG image.
7. Fixed an ArrayIndexOutOfBoundsException in the TJExample Java program that
occurred when attempting to decompress a JPEG image that had been compressed
with 4:1:1 chrominance subsampling.
8. Fixed an issue whereby, when using `jpeg_skip_scanlines()` to skip to the
end of a single-scan (non-progressive) image, subsequent calls to
`jpeg_consume_input()` would return `JPEG_SUSPENDED` rather than
`JPEG_REACHED_EOI`.
9. `jpeg_crop_scanlines()` now works correctly when decompressing grayscale
JPEG images that were compressed with a sampling factor other than 1 (for
instance, with `cjpeg -grayscale -sample 2x2`).
1.5.2
=====

View File

@ -216,7 +216,7 @@ compute_reciprocal (UINT16 divisor, DCTELEM *dtbl)
#endif
dtbl[DCTSIZE2 * 3] = (DCTELEM) r - sizeof(DCTELEM)*8; /* shift */
if(r <= 16) return 0;
if (r <= 16) return 0;
else return 1;
}

View File

@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1994-1996, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright (C) 2010, 2015-2016, D. R. Commander.
* Copyright (C) 2010, 2015-2017, D. R. Commander.
* Copyright (C) 2015, Google, Inc.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
@ -190,7 +190,10 @@ jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset,
* single-pass decompression case, allowing us to use the same MCU column
* width for all of the components.
*/
align = cinfo->_min_DCT_scaled_size * cinfo->max_h_samp_factor;
if (cinfo->comps_in_scan == 1 && cinfo->num_components == 1)
align = cinfo->_min_DCT_scaled_size;
else
align = cinfo->_min_DCT_scaled_size * cinfo->max_h_samp_factor;
/* Adjust xoffset to the nearest iMCU boundary <= the requested value */
input_xoffset = *xoffset;
@ -215,6 +218,9 @@ jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset,
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
int hsf = (cinfo->comps_in_scan == 1 && cinfo->num_components == 1) ?
1 : compptr->h_samp_factor;
/* Set downsampled_width to the new output width. */
orig_downsampled_width = compptr->downsampled_width;
compptr->downsampled_width =
@ -228,11 +234,10 @@ jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset,
* values will be used in multi-scan decompressions.
*/
cinfo->master->first_MCU_col[ci] =
(JDIMENSION) (long) (*xoffset * compptr->h_samp_factor) /
(long) align;
(JDIMENSION) (long) (*xoffset * hsf) / (long) align;
cinfo->master->last_MCU_col[ci] =
(JDIMENSION) jdiv_round_up((long) ((*xoffset + cinfo->output_width) *
compptr->h_samp_factor),
hsf),
(long) align) - 1;
}
@ -293,6 +298,14 @@ noop_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
}
/* Dummy quantize function used by jpeg_skip_scanlines() */
LOCAL(void)
noop_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
JSAMPARRAY output_buf, int num_rows)
{
}
/*
* In some cases, it is best to call jpeg_read_scanlines() and discard the
* output, rather than skipping the scanlines, because this allows us to
@ -308,14 +321,22 @@ read_and_discard_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines)
void (*color_convert) (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
JDIMENSION input_row, JSAMPARRAY output_buf,
int num_rows);
void (*color_quantize) (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
JSAMPARRAY output_buf, int num_rows) = NULL;
color_convert = cinfo->cconvert->color_convert;
cinfo->cconvert->color_convert = noop_convert;
if (cinfo->cquantize && cinfo->cquantize->color_quantize) {
color_quantize = cinfo->cquantize->color_quantize;
cinfo->cquantize->color_quantize = noop_quantize;
}
for (n = 0; n < num_lines; n++)
jpeg_read_scanlines(cinfo, NULL, 1);
cinfo->cconvert->color_convert = color_convert;
if (color_quantize)
cinfo->cquantize->color_quantize = color_quantize;
}
@ -370,6 +391,8 @@ jpeg_skip_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines)
/* Do not skip past the bottom of the image. */
if (cinfo->output_scanline + num_lines >= cinfo->output_height) {
cinfo->output_scanline = cinfo->output_height;
(*cinfo->inputctl->finish_input_pass) (cinfo);
cinfo->inputctl->eoi_reached = TRUE;
return cinfo->output_height - cinfo->output_scanline;
}

View File

@ -616,7 +616,7 @@ static const JLONG dither_matrix[4] = {
static INLINE boolean is_big_endian(void)
{
int test_value = 1;
if(*(char *)&test_value != 1)
if (*(char *)&test_value != 1)
return TRUE;
return FALSE;
}

View File

@ -503,7 +503,7 @@ static const JLONG dither_matrix[4] = {
static INLINE boolean is_big_endian(void)
{
int test_value = 1;
if(*(char *)&test_value != 1)
if (*(char *)&test_value != 1)
return TRUE;
return FALSE;
}

View File

@ -16,6 +16,8 @@ DEFINES += HAVE_CONFIG_H
# platform/compiler specific definitions
uikit|qnx|winrt: DEFINES += PCRE2_DISABLE_JIT
win32:contains(QT_ARCH, "arm"): DEFINES += PCRE2_DISABLE_JIT
win32:contains(QT_ARCH, "arm64"): DEFINES += PCRE2_DISABLE_JIT
SOURCES += \
$$PWD/src/pcre2_auto_possess.c \

View File

@ -4,7 +4,7 @@ CONFIG += exceptions
DEFINES += QT_NO_USING_NAMESPACE QT_NO_FOREACH
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x66000000
msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x66000000
QMAKE_DOCS = $$PWD/doc/qtconcurrent.qdocconf

View File

@ -12,7 +12,7 @@ CONFIG += qt_tracepoints
CONFIG += $$MODULE_CONFIG
DEFINES += $$MODULE_DEFINES
DEFINES += QT_NO_USING_NAMESPACE QT_NO_FOREACH
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x67000000
msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x67000000
CONFIG += simd optimize_full

View File

@ -74,7 +74,7 @@ DECLSPEC_IMPORT BOOLEAN WINAPI SystemFunction036(PVOID RandomBuffer, ULONG Rando
}
#endif
#if defined(Q_OS_ANDROID)
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
# include <private/qjni_p.h>
#endif

View File

@ -185,10 +185,11 @@ bool QFSFileEnginePrivate::nativeFlush()
bool QFSFileEnginePrivate::nativeSyncToDisk()
{
Q_Q(QFSFileEngine);
int ret;
#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
const int ret = fdatasync(nativeHandle());
EINTR_LOOP(ret, fdatasync(nativeHandle()));
#else
const int ret = fsync(nativeHandle());
EINTR_LOOP(ret, fsync(nativeHandle()));
#endif
if (ret != 0)
q->setError(QFile::WriteError, qt_error_string(errno));

View File

@ -905,6 +905,7 @@ bool QEventDispatcherWin32::registerEventNotifier(QWinEventNotifier *notifier)
return true;
d->winEventNotifierList.append(notifier);
d->winEventNotifierListModified = true;
if (!d->winEventNotifierActivatedEvent)
d->winEventNotifierActivatedEvent = CreateEvent(0, TRUE, FALSE, nullptr);
@ -928,6 +929,7 @@ void QEventDispatcherWin32::unregisterEventNotifier(QWinEventNotifier *notifier)
if (i == -1)
return;
d->winEventNotifierList.takeAt(i);
d->winEventNotifierListModified = true;
QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier);
if (nd->waitHandle)
nd->unregisterWaitObject();
@ -938,16 +940,19 @@ void QEventDispatcherWin32::activateEventNotifiers()
Q_D(QEventDispatcherWin32);
ResetEvent(d->winEventNotifierActivatedEvent);
// Iterate backwards, because the notifier might remove itself on activate().
for (int i = d->winEventNotifierList.count(); --i >= 0;) {
QWinEventNotifier *notifier = d->winEventNotifierList.at(i);
QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier);
if (nd->signaledCount.load() != 0) {
--nd->signaledCount;
nd->unregisterWaitObject();
d->activateEventNotifier(notifier);
// Activate signaled notifiers. Our winEventNotifierList can be modified in activation slots.
do {
d->winEventNotifierListModified = false;
for (int i = 0; i < d->winEventNotifierList.count(); ++i) {
QWinEventNotifier *notifier = d->winEventNotifierList.at(i);
QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier);
if (nd->signaledCount.load() != 0) {
--nd->signaledCount;
nd->unregisterWaitObject();
d->activateEventNotifier(notifier);
}
}
}
} while (d->winEventNotifierListModified);
// Re-register the remaining activated notifiers.
for (int i = 0; i < d->winEventNotifierList.count(); ++i) {

View File

@ -195,6 +195,7 @@ public:
HANDLE winEventNotifierActivatedEvent;
QList<QWinEventNotifier *> winEventNotifierList;
bool winEventNotifierListModified = false;
void activateEventNotifier(QWinEventNotifier * wen);
QList<MSG> queuedUserInputEvents;

View File

@ -6887,6 +6887,8 @@ QString QString::vasprintf(const char *cformat, va_list ap)
\snippet qstring/main.cpp 74
This function ignores leading and trailing whitespace.
\sa number(), toULongLong(), toInt(), QLocale::toLongLong()
*/
@ -6927,6 +6929,8 @@ qlonglong QString::toIntegral_helper(const QChar *data, int len, bool *ok, int b
\snippet qstring/main.cpp 79
This function ignores leading and trailing whitespace.
\sa number(), toLongLong(), QLocale::toULongLong()
*/
@ -6969,6 +6973,8 @@ qulonglong QString::toIntegral_helper(const QChar *data, uint len, bool *ok, int
\snippet qstring/main.cpp 73
This function ignores leading and trailing whitespace.
\sa number(), toULong(), toInt(), QLocale::toInt()
*/
@ -6998,6 +7004,8 @@ long QString::toLong(bool *ok, int base) const
\snippet qstring/main.cpp 78
This function ignores leading and trailing whitespace.
\sa number(), QLocale::toUInt()
*/
@ -7026,6 +7034,8 @@ ulong QString::toULong(bool *ok, int base) const
\snippet qstring/main.cpp 72
This function ignores leading and trailing whitespace.
\sa number(), toUInt(), toDouble(), QLocale::toInt()
*/
@ -7053,6 +7063,8 @@ int QString::toInt(bool *ok, int base) const
\snippet qstring/main.cpp 77
This function ignores leading and trailing whitespace.
\sa number(), toInt(), QLocale::toUInt()
*/
@ -7080,6 +7092,8 @@ uint QString::toUInt(bool *ok, int base) const
\snippet qstring/main.cpp 76
This function ignores leading and trailing whitespace.
\sa number(), toUShort(), toInt(), QLocale::toShort()
*/
@ -7107,6 +7121,8 @@ short QString::toShort(bool *ok, int base) const
\snippet qstring/main.cpp 80
This function ignores leading and trailing whitespace.
\sa number(), toShort(), QLocale::toUShort()
*/
@ -7126,7 +7142,10 @@ ushort QString::toUShort(bool *ok, int base) const
\snippet qstring/main.cpp 66
\warning The QString content may only contain valid numerical characters which includes the plus/minus sign, the characters g and e used in scientific notation, and the decimal point. Including the unit or additional characters leads to a conversion error.
\warning The QString content may only contain valid numerical characters
which includes the plus/minus sign, the characters g and e used in scientific
notation, and the decimal point. Including the unit or additional characters
leads to a conversion error.
\snippet qstring/main.cpp 67
@ -7141,6 +7160,8 @@ ushort QString::toUShort(bool *ok, int base) const
\snippet qstring/main.cpp 69
This function ignores leading and trailing whitespace.
\sa number(), QLocale::setDefault(), QLocale::toDouble(), trimmed()
*/
@ -7155,6 +7176,8 @@ double QString::toDouble(bool *ok) const
If a conversion error occurs, *\a{ok} is set to \c false; otherwise
*\a{ok} is set to \c true. Returns 0.0 if the conversion fails.
This function ignores leading and trailing whitespace.
The string conversion will always happen in the 'C' locale. For locale
dependent conversion use QLocale::toFloat()
@ -7162,6 +7185,8 @@ double QString::toDouble(bool *ok) const
\snippet qstring/main.cpp 71
This function ignores leading and trailing whitespace.
\sa number(), toDouble(), toInt(), QLocale::toFloat()
*/

View File

@ -470,6 +470,10 @@ bool QMoviePrivate::next()
currentPixmap = QPixmap::fromImage( info.pixmap.toImage().scaled(scaledSize) );
else
currentPixmap = info.pixmap;
if (!speed)
return true;
nextDelay = speedAdjustedDelay(info.delay);
// Adjust delay according to the time it took to read the frame
int processingTime = time.elapsed();
@ -504,7 +508,7 @@ void QMoviePrivate::_q_loadNextFrame(bool starting)
emit q->updated(frameRect);
emit q->frameChanged(currentFrameNumber);
if (movieState == QMovie::Running)
if (speed && movieState == QMovie::Running)
nextImageTimer.start(nextDelay);
} else {
// Could not read another frame
@ -926,6 +930,8 @@ void QMovie::setPaused(bool paused)
void QMovie::setSpeed(int percentSpeed)
{
Q_D(QMovie);
if (!d->speed && d->movieState == Running)
d->nextImageTimer.start(nextFrameDelay());
d->speed = percentSpeed;
}

View File

@ -283,9 +283,10 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleApplicationStateChanged, Qt::Application
QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow *window, const QRect &newGeometry)
: WindowSystemEvent(GeometryChange)
, window(window)
, requestedGeometry(window->handle() ? window->handle()->QPlatformWindow::geometry() : QRect())
, newGeometry(newGeometry)
{
if (const QPlatformWindow *pw = window->handle())
requestedGeometry = QHighDpi::fromNativePixels(pw->QPlatformWindow::geometry(), window);
}
QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const QRect &newRect)

View File

@ -127,7 +127,7 @@ AVX2_SOURCES += painting/qdrawhelper_avx2.cpp
NEON_SOURCES += painting/qdrawhelper_neon.cpp painting/qimagescale_neon.cpp
NEON_HEADERS += painting/qdrawhelper_neon_p.h
NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S
!uikit:contains(QT_ARCH, "arm"): CONFIG += no_clang_integrated_as
!uikit:!win32:contains(QT_ARCH, "arm"): CONFIG += no_clang_integrated_as
!uikit:!win32:!contains(QT_ARCH, "arm64"): DEFINES += ENABLE_PIXMAN_DRAWHELPERS
MIPS_DSP_SOURCES += painting/qdrawhelper_mips_dsp.cpp

View File

@ -354,7 +354,7 @@ void QHttpNetworkConnectionPrivate::prepareRequest(HttpMessagePair &messagePair)
host += QByteArray::number(port);
}
request.setHeaderField("Host", host);
request.prependHeaderField("Host", host);
}
reply->d_func()->requestIsPrepared = true;

View File

@ -112,6 +112,11 @@ void QHttpNetworkHeaderPrivate::setHeaderField(const QByteArray &name, const QBy
fields.append(qMakePair(name, data));
}
void QHttpNetworkHeaderPrivate::prependHeaderField(const QByteArray &name, const QByteArray &data)
{
fields.prepend(qMakePair(name, data));
}
bool QHttpNetworkHeaderPrivate::operator==(const QHttpNetworkHeaderPrivate &other) const
{
return (url == other.url);

View File

@ -92,6 +92,7 @@ public:
QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const;
QList<QByteArray> headerFieldValues(const QByteArray &name) const;
void setHeaderField(const QByteArray &name, const QByteArray &data);
void prependHeaderField(const QByteArray &name, const QByteArray &data);
bool operator==(const QHttpNetworkHeaderPrivate &other) const;
};

View File

@ -279,6 +279,11 @@ void QHttpNetworkRequest::setHeaderField(const QByteArray &name, const QByteArra
d->setHeaderField(name, data);
}
void QHttpNetworkRequest::prependHeaderField(const QByteArray &name, const QByteArray &data)
{
d->prependHeaderField(name, data);
}
QHttpNetworkRequest &QHttpNetworkRequest::operator=(const QHttpNetworkRequest &other)
{
d = other.d;

View File

@ -102,6 +102,7 @@ public:
QList<QPair<QByteArray, QByteArray> > header() const override;
QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const override;
void setHeaderField(const QByteArray &name, const QByteArray &data) override;
void prependHeaderField(const QByteArray &name, const QByteArray &data);
Operation operation() const;
void setOperation(Operation operation);

View File

@ -141,10 +141,10 @@
"use": "network"
},
"openssl11": {
"label": "OpenSSL v. 1.1 support",
"label": "OpenSSL 1.1 support",
"type": "compile",
"test": "unix/openssl11",
"use": "network"
"use": "openssl"
}
},
@ -213,9 +213,9 @@
"output": [ "publicFeature", "feature" ]
},
"opensslv11": {
"label": "OpenSSL v. 1.1",
"condition": "tests.openssl11",
"output": ["publicFeature", "feature"]
"label": "OpenSSL 1.1",
"condition": "features.openssl && tests.openssl11",
"output": [ "publicFeature" ]
},
"sctp": {
"label": "SCTP",
@ -341,6 +341,7 @@ For example:
},
"openssl",
"openssl-linked",
"opensslv11",
"sctp",
"system-proxies"
]

View File

@ -10,7 +10,7 @@ DEFINES += QT_NO_USING_NAMESPACE QT_NO_FOREACH
#DEFINES += QTCPSOCKETENGINE_DEBUG QTCPSOCKET_DEBUG QTCPSERVER_DEBUG QSSLSOCKET_DEBUG
#DEFINES += QUDPSOCKET_DEBUG QUDPSERVER_DEBUG
#DEFINES += QSCTPSOCKET_DEBUG QSCTPSERVER_DEBUG
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x64000000
msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x64000000
QMAKE_DOCS = $$PWD/doc/qtnetwork.qdocconf

View File

@ -3,7 +3,7 @@ QT = core-private gui-private widgets-private
DEFINES += QT_NO_USING_NAMESPACE QT_NO_FOREACH
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x63000000
msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x63000000
solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
QMAKE_DOCS = $$PWD/doc/qtopengl.qdocconf

View File

@ -40,6 +40,8 @@
#import "qcocoansmenu.h"
#include "qcocoamenu.h"
#include "qcocoamenuitem.h"
#include "qcocoamenubar.h"
#include "qcocoawindow.h"
#import "qnsview.h"
#include <QtCore/qmetaobject.h>
@ -291,6 +293,19 @@ static NSString *qt_mac_removePrivateUnicode(NSString* string)
return nil;
}
// Cocoa will query the menu item's target for the worksWhenModal selector.
// So we need to implement this to allow the items to be handled correctly
// when a modal dialog is visible.
- (BOOL)worksWhenModal
{
if (!QGuiApplication::modalWindow())
return YES;
const auto &qpaMenu = static_cast<QCocoaNSMenu *>(self).qpaMenu;
if (auto *mb = qobject_cast<QCocoaMenuBar *>(qpaMenu->menuParent()))
return QGuiApplication::modalWindow()->handle() == mb->cocoaWindow() ? YES : NO;
return YES;
}
@end
#undef CHECK_MENU_CLASS

View File

@ -503,9 +503,10 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags)
{
const Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
const bool frameless = (flags & Qt::FramelessWindowHint) || windowIsPopupType(type);
const bool resizeable = type != Qt::Dialog; // Dialogs: remove zoom button by disabling resize
// Select base window type.
NSUInteger styleMask = frameless ? NSBorderlessWindowMask : NSResizableWindowMask;
// Select base window type. Note that the value of NSBorderlessWindowMask is 0.
NSUInteger styleMask = (frameless || !resizeable) ? NSBorderlessWindowMask : NSResizableWindowMask;
if (frameless) {
// No further customizations for frameless since there are no window decorations.
@ -1156,23 +1157,6 @@ void QCocoaWindow::handleExposeEvent(const QRegion &region)
m_exposedRect = QRect();
}
QWindowPrivate *windowPrivate = qt_window_private(window());
if (windowPrivate->updateRequestPending) {
// We can only deliver update request events when the window is exposed,
// and we also have to make sure we deliver any change to the exposed
// rect as a real expose event (including going from non-exposed to
// exposed). FIXME: Should this logic live in QGuiApplication?
if (isExposed() && m_exposedRect == previouslyExposedRect) {
qCDebug(lcQpaCocoaDrawing) << "QCocoaWindow::handleExposeEvent" << window() << region << "as update request";
windowPrivate->deliverUpdateRequest();
return;
} else {
// Since updateRequestPending is still set, we will issue a deferred setNeedsDisplay
// from drawRect and get back into this code on the next display cycle, delivering
// the pending update request.
}
}
qCDebug(lcQpaCocoaDrawing) << "QCocoaWindow::handleExposeEvent" << window() << region << "isExposed" << isExposed();
QWindowSystemInterface::handleExposeEvent<QWindowSystemInterface::SynchronousDelivery>(window(), region);
}
@ -1347,7 +1331,7 @@ void QCocoaWindow::recreateWindowIfNeeded()
void QCocoaWindow::requestUpdate()
{
qCDebug(lcQpaCocoaDrawing) << "QCocoaWindow::requestUpdate" << window();
[m_view setNeedsDisplay:YES];
[m_view requestUpdate];
}
void QCocoaWindow::requestActivateWindow()

View File

@ -81,6 +81,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
NSEvent *m_currentlyInterpretedKeyEvent;
bool m_isMenuView;
QSet<quint32> m_acceptedKeyDowns;
bool m_updateRequested;
}
@property (nonatomic, retain) NSCursor *cursor;
@ -105,6 +106,8 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
- (void)resetMouseButtons;
- (void)requestUpdate;
- (void)handleMouseEvent:(NSEvent *)theEvent;
- (bool)handleMouseDownEvent:(NSEvent *)theEvent withButton:(int)buttonNumber;
- (bool)handleMouseDraggedEvent:(NSEvent *)theEvent withButton:(int)buttonNumber;

View File

@ -148,6 +148,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
m_isMenuView = false;
self.focusRingType = NSFocusRingTypeNone;
self.cursor = nil;
m_updateRequested = false;
}
return self;
}
@ -300,6 +301,25 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
return m_platformWindow->isOpaque();
}
- (void)requestUpdate
{
if (self.needsDisplay) {
// If the view already has needsDisplay set it means that there may be code waiting for
// a real expose event, so we can't issue setNeedsDisplay now as a way to trigger an
// update request. We will re-trigger requestUpdate from drawRect.
return;
}
[self setNeedsDisplay:YES];
m_updateRequested = true;
}
- (void)setNeedsDisplayInRect:(NSRect)rect
{
[super setNeedsDisplayInRect:rect];
m_updateRequested = false;
}
- (void)drawRect:(NSRect)dirtyRect
{
Q_UNUSED(dirtyRect);
@ -315,7 +335,11 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
exposedRegion += QRectF::fromCGRect(dirtyRects[i]).toRect();
qCDebug(lcQpaCocoaDrawing) << "[QNSView drawRect:]" << m_platformWindow->window() << exposedRegion;
[self updateRegion:exposedRegion];
}
- (void)updateRegion:(QRegion)dirtyRegion
{
#ifndef QT_NO_OPENGL
if (m_glContext && m_shouldSetGLContextinDrawRect) {
[m_glContext->nsOpenGLContext() setView:self];
@ -323,18 +347,24 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
}
#endif
m_platformWindow->handleExposeEvent(exposedRegion);
QWindowPrivate *windowPrivate = qt_window_private(m_platformWindow->window());
if (qt_window_private(m_platformWindow->window())->updateRequestPending) {
// A call to QWindow::requestUpdate was issued during the expose event, or we
// had to deliver a real expose event and still need to deliver the update.
// But AppKit will reset the needsDisplay state of the view after completing
if (m_updateRequested) {
Q_ASSERT(windowPrivate->updateRequestPending);
qCDebug(lcQpaCocoaWindow) << "Delivering update request to" << m_platformWindow->window();
windowPrivate->deliverUpdateRequest();
m_updateRequested = false;
} else {
m_platformWindow->handleExposeEvent(dirtyRegion);
}
if (windowPrivate->updateRequestPending) {
// A call to QWindow::requestUpdate was issued during event delivery above,
// but AppKit will reset the needsDisplay state of the view after completing
// the current display cycle, so we need to defer the request to redisplay.
// FIXME: Perhaps this should be a trigger to enable CADisplayLink?
qCDebug(lcQpaCocoaDrawing) << "[QNSView drawRect:] issuing deferred setNeedsDisplay due to pending update request";
dispatch_async(dispatch_get_main_queue (), ^{
[self setNeedsDisplay:YES];
});
dispatch_async(dispatch_get_main_queue (), ^{ [self requestUpdate]; });
}
}
@ -351,7 +381,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
qCDebug(lcQpaCocoaDrawing) << "[QNSView updateLayer]" << m_platformWindow->window();
// FIXME: Find out if there's a way to resolve the dirty rect like in drawRect:
m_platformWindow->handleExposeEvent(QRectF::fromCGRect(self.bounds).toRect());
[self updateRegion:QRectF::fromCGRect(self.bounds).toRect()];
}
- (void)viewDidChangeBackingProperties

View File

@ -110,6 +110,10 @@ private:
friend class QIOSScreen;
};
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QIOSWindow *window);
#endif
QT_END_NAMESPACE
#endif // QIOSWINDOW_H

View File

@ -381,6 +381,19 @@ CAEAGLLayer *QIOSWindow::eaglLayer() const
return static_cast<CAEAGLLayer *>(m_view.layer);
}
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QIOSWindow *window)
{
QDebugStateSaver saver(debug);
debug.nospace();
debug << "QIOSWindow(" << (const void *)window;
if (window)
debug << ", window=" << window->window();
debug << ')';
return debug;
}
#endif // !QT_NO_DEBUG_STREAM
#include "moc_qioswindow.cpp"
QT_END_NAMESPACE

View File

@ -149,6 +149,21 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
[super dealloc];
}
- (NSString *)description
{
NSMutableString *description = [NSMutableString stringWithString:[super description]];
#ifndef QT_NO_DEBUG_STREAM
QString platformWindowDescription;
QDebug debug(&platformWindowDescription);
debug.nospace() << "; " << m_qioswindow << ">";
NSRange lastCharacter = [description rangeOfComposedCharacterSequenceAtIndex:description.length - 1];
[description replaceCharactersInRange:lastCharacter withString:platformWindowDescription.toNSString()];
#endif
return description;
}
- (void)willMoveToWindow:(UIWindow *)newWindow
{
// UIKIt will normally set the scale factor of a view to match the corresponding
@ -193,13 +208,12 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
// when the size is also changed.
if (!CGAffineTransformIsIdentity(self.transform))
qWarning() << m_qioswindow->window()
<< "is backed by a UIView that has a transform set. This is not supported.";
qWarning() << self << "has a transform set. This is not supported.";
QWindow *window = m_qioswindow->window();
QRect lastReportedGeometry = qt_window_private(window)->geometry;
QRect currentGeometry = QRectF::fromCGRect(self.frame).toRect();
qCDebug(lcQpaWindow) << m_qioswindow->window() << "new geometry is" << currentGeometry;
qCDebug(lcQpaWindow) << m_qioswindow << "new geometry is" << currentGeometry;
QWindowSystemInterface::handleGeometryChange(window, currentGeometry);
if (currentGeometry.size() != lastReportedGeometry.size()) {
@ -232,7 +246,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
region = QRect(QPoint(), bounds);
}
qCDebug(lcQpaWindow) << m_qioswindow->window() << region << "isExposed" << m_qioswindow->isExposed();
qCDebug(lcQpaWindow) << m_qioswindow << region << "isExposed" << m_qioswindow->isExposed();
QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), region);
}
@ -256,16 +270,14 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
// blocked by this guard.
FirstResponderCandidate firstResponderCandidate(self);
qImDebug() << "win:" << m_qioswindow->window() << "self:" << self
<< "first:" << [UIResponder currentFirstResponder];
qImDebug() << "self:" << self << "first:" << [UIResponder currentFirstResponder];
if (![super becomeFirstResponder]) {
qImDebug() << m_qioswindow->window()
<< "was not allowed to become first responder";
qImDebug() << self << "was not allowed to become first responder";
return NO;
}
qImDebug() << m_qioswindow->window() << "became first responder";
qImDebug() << self << "became first responder";
}
if (qGuiApp->focusWindow() != m_qioswindow->window())
@ -297,13 +309,12 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
- (BOOL)resignFirstResponder
{
qImDebug() << "win:" << m_qioswindow->window() << "self:" << self
<< "first:" << [UIResponder currentFirstResponder];
qImDebug() << "self:" << self << "first:" << [UIResponder currentFirstResponder];
if (![super resignFirstResponder])
return NO;
qImDebug() << m_qioswindow->window() << "resigned first responder";
qImDebug() << self << "resigned first responder";
UIResponder *newResponder = FirstResponderCandidate::currentCandidate();
if ([self responderShouldTriggerWindowDeactivation:newResponder])

View File

@ -980,8 +980,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::QuerySizeHints:
d->m_creationContext->applyToMinMaxInfo(reinterpret_cast<MINMAXINFO *>(lParam));
return true;
case QtWindows::ResizeEvent:
d->m_creationContext->obtainedGeometry.setSize(QSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
case QtWindows::ResizeEvent: {
const QSize size(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) - d->m_creationContext->menuHeight);
d->m_creationContext->obtainedGeometry.setSize(size);
}
return true;
case QtWindows::MoveEvent:
d->m_creationContext->obtainedGeometry.moveTo(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));

View File

@ -1034,8 +1034,10 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w,
const QMargins effectiveMargins = margins + customMargins;
frameWidth = effectiveMargins.left() + geometry.width() + effectiveMargins.right();
frameHeight = effectiveMargins.top() + geometry.height() + effectiveMargins.bottom();
if (QWindowsMenuBar::menuBarOf(w) != nullptr)
frameHeight += GetSystemMetrics(SM_CYMENU);
if (QWindowsMenuBar::menuBarOf(w) != nullptr) {
menuHeight = GetSystemMetrics(SM_CYMENU);
frameHeight += menuHeight;
}
const bool isDefaultPosition = !frameX && !frameY && w->isTopLevel();
if (!QWindowsGeometryHint::positionIncludesFrame(w) && !isDefaultPosition) {
frameX -= effectiveMargins.left();

View File

@ -101,6 +101,7 @@ struct QWindowCreationContext
int frameY = CW_USEDEFAULT;
int frameWidth = CW_USEDEFAULT;
int frameHeight = CW_USEDEFAULT;
int menuHeight = 0;
};
struct QWindowsWindowData

View File

@ -2,7 +2,7 @@ TARGET = QtSql
QT = core-private
DEFINES += QT_NO_USING_NAMESPACE
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x62000000
msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x62000000
QMAKE_DOCS = $$PWD/doc/qtsql.qdocconf

View File

@ -313,13 +313,15 @@ void QGraphicsViewPrivate::translateTouchEvent(QGraphicsViewPrivate *d, QTouchEv
QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
for (int i = 0; i < touchPoints.count(); ++i) {
QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
const QSizeF ellipseDiameters = touchPoint.ellipseDiameters();
// the scene will set the item local pos, startPos, lastPos, and rect before delivering to
// an item, but for now those functions are returning the view's local coordinates
touchPoint.setSceneRect(d->mapToScene(touchPoint.rect()));
touchPoint.setScenePos(d->mapToScene(touchPoint.pos()));
touchPoint.setStartScenePos(d->mapToScene(touchPoint.startPos()));
touchPoint.setLastScenePos(d->mapToScene(touchPoint.lastPos()));
touchPoint.setEllipseDiameters(ellipseDiameters);
// screenPos, startScreenPos, lastScreenPos, and screenRect are already set
// screenPos, startScreenPos, and lastScreenPos are already set
}
touchEvent->setTouchPoints(touchPoints);

View File

@ -2847,7 +2847,7 @@ void QApplication::setStartDragDistance(int l)
and the current position (e.g. in the mouse move event) is \c currentPos,
you can find out if a drag should be started with code like this:
\snippet code/src_gui_kernel_qapplication.cpp 6
\snippet code/src_gui_kernel_qapplication.cpp 7
Qt uses this value internally, e.g. in QFileDialog.

View File

@ -4,7 +4,7 @@ MODULE_CONFIG = uic
CONFIG += $$MODULE_CONFIG
DEFINES += QT_NO_USING_NAMESPACE
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x65000000
msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x65000000
QMAKE_DOCS = $$PWD/doc/qtwidgets.qdocconf

View File

@ -3,7 +3,7 @@ QT = core-private
DEFINES += QT_NO_USING_NAMESPACE QT_NO_FOREACH
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x61000000
msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x61000000
QMAKE_DOCS = $$PWD/doc/qtxml.qdocconf

View File

@ -29,8 +29,11 @@
#include <QtTest/QtTest>
#include <qwineventnotifier.h>
#include <qtimer.h>
#include <qvarlengtharray.h>
#include <qvector.h>
#include <qt_windows.h>
#include <algorithm>
#include <memory>
class tst_QWinEventNotifier : public QObject
@ -44,6 +47,8 @@ private slots:
void simple_data();
void simple();
void manyNotifiers();
void disableNotifiersInActivatedSlot_data();
void disableNotifiersInActivatedSlot();
private:
HANDLE simpleHEvent;
@ -109,9 +114,6 @@ public:
this, &EventWithNotifier::onNotifierActivated);
notifier.setHandle(CreateEvent(0, TRUE, FALSE, 0));
notifier.setEnabled(true);
static int nextIndex = 0;
idx = nextIndex++;
}
~EventWithNotifier()
@ -122,6 +124,7 @@ public:
HANDLE eventHandle() const { return notifier.handle(); }
int numberOfTimesActivated() const { return activatedCount; }
void setEnabled(bool b) { notifier.setEnabled(b); }
signals:
void activated();
@ -137,7 +140,6 @@ public slots:
private:
QWinEventNotifier notifier;
int activatedCount = 0;
int idx = 0;
};
void tst_QWinEventNotifier::manyNotifiers()
@ -184,6 +186,60 @@ void tst_QWinEventNotifier::manyNotifiers()
}));
}
using Indices = QVector<int>;
void tst_QWinEventNotifier::disableNotifiersInActivatedSlot_data()
{
QTest::addColumn<int>("count");
QTest::addColumn<Indices>("notifiersToSignal");
QTest::addColumn<Indices>("notifiersToDisable");
QTest::addColumn<bool>("deleteNotifiers");
QTest::newRow("disable_signaled") << 3 << Indices{1} << Indices{1} << false;
QTest::newRow("disable_signaled2") << 3 << Indices{1, 2} << Indices{1} << false;
QTest::newRow("disable_before_signaled") << 3 << Indices{1} << Indices{0, 1} << false;
QTest::newRow("disable_after_signaled") << 3 << Indices{1} << Indices{1, 2} << false;
QTest::newRow("delete_signaled") << 3 << Indices{1} << Indices{1} << true;
QTest::newRow("delete_before_signaled1") << 3 << Indices{1} << Indices{0} << true;
QTest::newRow("delete_before_signaled2") << 3 << Indices{1} << Indices{0, 1} << true;
QTest::newRow("delete_before_signaled3") << 4 << Indices{3, 1} << Indices{0, 1} << true;
QTest::newRow("delete_after_signaled1") << 3 << Indices{1} << Indices{1, 2} << true;
QTest::newRow("delete_after_signaled2") << 4 << Indices{1, 3} << Indices{1, 2} << true;
QTest::newRow("delete_after_signaled3") << 5 << Indices{1} << Indices{1, 4} << true;
}
void tst_QWinEventNotifier::disableNotifiersInActivatedSlot()
{
QFETCH(int, count);
QFETCH(Indices, notifiersToSignal);
QFETCH(Indices, notifiersToDisable);
QFETCH(bool, deleteNotifiers);
QVarLengthArray<std::unique_ptr<EventWithNotifier>, 10> events(count);
for (int i = 0; i < count; ++i)
events[i].reset(new EventWithNotifier);
auto isActivatedOrNull = [&events](int i) {
return !events.at(i) || events.at(i)->numberOfTimesActivated() > 0;
};
for (auto &e : events) {
connect(e.get(), &EventWithNotifier::activated, [&]() {
for (int i : notifiersToDisable) {
if (deleteNotifiers)
events[i].reset();
else
events.at(i)->setEnabled(false);
}
if (std::all_of(notifiersToSignal.begin(), notifiersToSignal.end(), isActivatedOrNull))
QTimer::singleShot(0, &QTestEventLoop::instance(), SLOT(exitLoop()));
});
}
for (int i : notifiersToSignal)
SetEvent(events.at(i)->eventHandle());
QTestEventLoop::instance().enterLoop(30);
QVERIFY(!QTestEventLoop::instance().timeout());
}
QTEST_MAIN(tst_QWinEventNotifier)
#include "tst_qwineventnotifier.moc"

View File

@ -170,6 +170,16 @@ void tst_QMovie::playMovie()
QCOMPARE(movie.state(), QMovie::NotRunning);
QCOMPARE(movie.frameCount(), frameCount);
#endif
movie.stop();
QSignalSpy finishedSpy(&movie, &QMovie::finished);
movie.setSpeed(0);
movie.start();
QCOMPARE(movie.state(), QMovie::Running);
QTestEventLoop::instance().enterLoop(2);
QCOMPARE(finishedSpy.count(), 0);
QCOMPARE(movie.state(), QMovie::Running);
QCOMPARE(movie.currentFrameNumber(), 0);
}
void tst_QMovie::jumpToFrame_data()

View File

@ -254,6 +254,7 @@ private slots:
void zeroScale();
void focusItemChangedSignal();
void minimumRenderSize();
void checkTouchPointsEllipseDiameters();
// task specific tests below me
void task139710_bspTreeCrash();
@ -4764,6 +4765,81 @@ void tst_QGraphicsScene::minimumRenderSize()
QVERIFY(smallChild->repaints > smallerGrandChild->repaints);
}
class TouchItem : public QGraphicsRectItem
{
public:
TouchItem() : QGraphicsRectItem(QRectF(-10, -10, 20, 20)),
seenTouch(false)
{
setAcceptTouchEvents(true);
setFlag(QGraphicsItem::ItemIgnoresTransformations);
}
bool seenTouch;
QList<QTouchEvent::TouchPoint> touchPoints;
protected:
bool sceneEvent(QEvent *event) override
{
switch (event->type()) {
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
seenTouch = true;
touchPoints = static_cast<QTouchEvent *>(event)->touchPoints();
event->accept();
return true;
default:
break;
}
return QGraphicsRectItem::sceneEvent(event);
}
};
void tst_QGraphicsScene::checkTouchPointsEllipseDiameters()
{
QGraphicsScene scene;
QGraphicsView view(&scene);
scene.setSceneRect(1, 1, 198, 198);
view.scale(1.5, 1.5);
view.setFocus();
TouchItem *rect = new TouchItem;
scene.addItem(rect);
view.show();
QApplication::setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowActive(&view));
const QSizeF ellipseDiameters(10.0, 10.0);
QTouchEvent::TouchPoint touchPoint(0);
touchPoint.setState(Qt::TouchPointPressed);
touchPoint.setPos(view.mapFromScene(rect->mapToScene(rect->boundingRect().center())));
touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint()));
touchPoint.setEllipseDiameters(ellipseDiameters);
QList<QTouchEvent::TouchPoint> touchPoints = { touchPoint };
QTouchDevice *testDevice = QTest::createTouchDevice(QTouchDevice::TouchPad);
QTouchEvent touchEvent(QEvent::TouchBegin,
testDevice,
Qt::NoModifier,
Qt::TouchPointPressed,
touchPoints);
QApplication::sendEvent(view.viewport(), &touchEvent);
QVERIFY(rect->seenTouch);
QVERIFY(rect->touchPoints.size() == 1);
QCOMPARE(ellipseDiameters, rect->touchPoints.first().ellipseDiameters());
rect->seenTouch = false;
rect->touchPoints.clear();
QTouchEvent touchUpdateEvent(QEvent::TouchUpdate,
testDevice,
Qt::NoModifier,
Qt::TouchPointMoved,
touchPoints);
QApplication::sendEvent(view.viewport(), &touchEvent);
QVERIFY(rect->seenTouch);
QVERIFY(rect->touchPoints.size() == 1);
QCOMPARE(ellipseDiameters, rect->touchPoints.first().ellipseDiameters());
}
void tst_QGraphicsScene::taskQTBUG_15977_renderWithDeviceCoordinateCache()
{
QGraphicsScene scene;

View File

@ -0,0 +1,163 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtWidgets>
class TouchableItem : public QGraphicsRectItem
{
public:
TouchableItem() : QGraphicsRectItem(50, 50, 400, 400)
{
setBrush(Qt::yellow);
setAcceptTouchEvents(true);
}
protected:
bool sceneEvent(QEvent *e)
{
const bool ret = QGraphicsRectItem::sceneEvent(e);
switch (e->type()) {
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
{
QTouchEvent *te = static_cast<QTouchEvent *>(e);
for (const QTouchEvent::TouchPoint &tp : te->touchPoints()) {
QGraphicsEllipseItem *diameterItem = nullptr;
QSizeF ellipse = tp.ellipseDiameters();
if (ellipse.isNull()) {
ellipse = QSizeF(5, 5);
} else {
diameterItem = new QGraphicsEllipseItem(QRectF(tp.pos().x() - ellipse.width() / 2, tp.pos().y() - ellipse.height() / 2,
ellipse.width(), ellipse.height()), this);
diameterItem->setPen(QPen(Qt::red));
diameterItem->setBrush(QBrush(Qt::red));
if (ellipse.width() > qreal(2) && ellipse.height() > qreal(2))
ellipse.scale(ellipse.width() - 2, ellipse.height() - 2, Qt::IgnoreAspectRatio);
}
QGraphicsItem *parent = diameterItem ? static_cast<QGraphicsItem *>(diameterItem) : static_cast<QGraphicsItem *>(this);
QGraphicsEllipseItem *ellipseItem = new QGraphicsEllipseItem(QRectF(tp.pos().x() - ellipse.width() / 2,
tp.pos().y() - ellipse.height() / 2,
ellipse.width(), ellipse.height()), parent);
ellipseItem->setPen(QPen(Qt::blue));
ellipseItem->setBrush(QBrush(Qt::blue));
}
te->accept();
return true;
}
default:
break;
}
return ret;
}
};
int main(int argc, char **argv)
{
QApplication a(argc, argv);
QMainWindow mw;
QWidget *w = new QWidget;
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(new QLabel("The blue ellipses should indicate touch point contact patches"));
qDebug() << "Touch devices:";
for (const QTouchDevice *device : QTouchDevice::devices()) {
QString result;
QTextStream str(&result);
str << (device->type() == QTouchDevice::TouchScreen ? "TouchScreen" : "TouchPad")
<< " \"" << device->name() << "\", max " << device->maximumTouchPoints()
<< " touch points, capabilities:";
const QTouchDevice::Capabilities capabilities = device->capabilities();
if (capabilities & QTouchDevice::Position)
str << " Position";
if (capabilities & QTouchDevice::Area)
str << " Area";
if (capabilities & QTouchDevice::Pressure)
str << " Pressure";
if (capabilities & QTouchDevice::Velocity)
str << " Velocity";
if (capabilities & QTouchDevice::RawPositions)
str << " RawPositions";
if (capabilities & QTouchDevice::NormalizedPosition)
str << " NormalizedPosition";
if (capabilities & QTouchDevice::MouseEmulation)
str << " MouseEmulation";
vbox->addWidget(new QLabel(result));
qDebug() << " " << result;
}
QGraphicsView *view = new QGraphicsView;
view->viewport()->setAttribute(Qt::WA_AcceptTouchEvents);
QGraphicsScene *scene = new QGraphicsScene(0, 0, 500, 500);
TouchableItem *touchableItem = new TouchableItem;
scene->addItem(touchableItem);
view->setScene(scene);
vbox->addWidget(view);
w->setLayout(vbox);
mw.setCentralWidget(w);
QMenu *menu = mw.menuBar()->addMenu("Menu");
QAction *clear = new QAction("Clear");
QObject::connect(clear, &QAction::triggered, [=]() {
qDeleteAll(touchableItem->childItems());
});
menu->addAction(clear);
QAction *ignoreTransform = new QAction("Ignore transformations");
QObject::connect(ignoreTransform, &QAction::triggered, [=]() {
view->scale(1.5, 1.5);
touchableItem->setFlag(QGraphicsItem::ItemIgnoresTransformations);
});
menu->addAction(ignoreTransform);
QAction *quit = new QAction("Quit");
quit->setShortcut(QKeySequence::Quit);
QObject::connect(quit, &QAction::triggered, &QApplication::quit);
menu->addAction(quit);
mw.show();
return a.exec();
}

View File

@ -0,0 +1,5 @@
QT+=widgets
TEMPLATE = app
TARGET = touchGraphicsItem
INCLUDEPATH += .
SOURCES += main.cpp