Merge remote-tracking branch 'origin/5.6' into dev

Change-Id: Ib43c6f126998eefcfed9a7c1f2bcbac8b4dd05ec
This commit is contained in:
Simon Hausmann 2015-11-27 08:27:03 +01:00
commit ea5f40a788
60 changed files with 1085 additions and 365 deletions

View File

@ -237,7 +237,7 @@ const char msg2[] = "==Qt=magic=Qt== Sub-architecture:"
#endif
// -- ARM --
#ifdef __ARM_NEON__
#if defined(__ARM_NEON) || defined(__ARM_NEON__)
" neon"
#endif
#ifdef __IWMMXT__

4
configure vendored
View File

@ -455,7 +455,7 @@ DeviceVar()
eq="="
;;
*)
echo >&2 "BUG: wrong command to QMakeVar: $1"
echo >&2 "BUG: wrong command to DeviceVar: $1"
;;
esac
@ -7203,7 +7203,7 @@ if [ -n "$DISABLED_FEATURES" ]; then
fi
echo "QT_QCONFIG_PATH = ${CFG_QCONFIG_PATH#$relpath/src/corelib/global/}"
cat >>"$QTMODULE.tmp" <<EOF
cat <<EOF
host_build {
QT_CPU_FEATURES.$CFG_HOST_ARCH = $CFG_HOST_CPUFEATURES
} else {

View File

@ -105,6 +105,10 @@
\externalpage http://doc.qt.io/qtcreator/qtcreator-transitions-example.html
\title Qt Creator: Creating a Qt Quick Application
*/
/*!
\externalpage http://doc.qt.io/qtcreator/qtquick-iso-icon-browser.html
\title Qt Creator: Browsing ISO 7000 Icons
*/
/*!
\externalpage http://doc.qt.io/qtcreator/quick-export-to-qml.html
\title Qt Creator: Exporting Designs from Graphics Software
@ -209,6 +213,10 @@
\externalpage http://doc.qt.io/qtcreator/creator-mime-types.html
\title Qt Creator: Editing MIME Types
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-modeling.html
\title Qt Creator: Modeling
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-qml-debugging-example.html
\title Qt Creator: Debugging a Qt Quick Example Application

View File

@ -1261,6 +1261,9 @@ table td,table th {
table.alignedsummary,table.propsummary {
width:initial
}
table.valuelist td.tblval {
font-size:0.75em
}
div.main_index .row {
border-bottom:1px solid #eee
}

View File

@ -19,6 +19,8 @@ if(win32|mac):!macx-xcode {
contains(QT_CONFIG, build_all):CONFIG += build_all
}
CONFIG += relative_qt_rpath # Qt's QML plugins should be relocatable
!no_cxx_module:isEmpty(CXX_MODULE) {
CXX_MODULE = $$TARGET
TARGET = declarative_$${TARGET}

View File

@ -120,15 +120,9 @@ defineTest(qtAddTargetEnv) {
deps = $$replace($$2, -private$, _private)
deps = $$resolve_depends(deps, "QT.", ".depends" ".run_depends")
!isEmpty(deps) {
ptypes =
for(dep, deps) {
isEmpty(3): \
deppath += $$shell_path($$eval(QT.$${dep}.libs))
else: \
deppath += $$system_path($$eval(QT.$${dep}.libs))
ptypes += $$eval(QT.$${dep}.plugin_types)
}
libs = libs
equals(QMAKE_HOST.os, Windows) {
libs = bins
deppath.name = PATH
} else:contains(QMAKE_HOST.os, Linux|FreeBSD|OpenBSD|NetBSD|DragonFly|SunOS|HP-UX|QNX|GNU) {
deppath.name = LD_LIBRARY_PATH
@ -144,6 +138,14 @@ defineTest(qtAddTargetEnv) {
} else {
error("Operating system not supported.")
}
ptypes =
for(dep, deps) {
isEmpty(3): \
deppath += $$shell_path($$eval(QT.$${dep}.$$libs))
else: \
deppath += $$system_path($$eval(QT.$${dep}.$$libs))
ptypes += $$eval(QT.$${dep}.plugin_types)
}
deppath.value = $$unique(deppath)
deppath.CONFIG = prepend

View File

@ -40,6 +40,10 @@ $(EXPORT_SUBTARGETS): % : %-build
%-install: ACTION = install
%-install: xcodebuild-% ;
# iOS Simulator doesn't support archiving
%-iphonesimulator-install: ACTION = build
iphonesimulator-install: ACTION = build
# Limit check to a single configuration
%-iphoneos-check: check-iphoneos ;
%-iphonesimulator-check: check-iphonesimulator ;

View File

@ -596,14 +596,11 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
continue;
}
x++;
int inc_len;
for (inc_len = 0;
buffer[x + inc_len] != term && !qmake_endOfLine(buffer[x + inc_len]);
++inc_len) {} // skip until end of include name
buffer[x + inc_len] = '\0';
inc = buffer + x;
x += inc_len;
for (;
buffer[x] != term && !qmake_endOfLine(buffer[x]);
++x) {} // skip until end of include name
buffer[x] = '\0';
} else if (buffer[x] == '\'' || buffer[x] == '"') {
const char term = buffer[x++];
while(x < buffer_len) {

View File

@ -1,4 +1,3 @@
DEFINES *= QT_USE_BUNDLED_LIBPNG
DEFINES += PNG_ARM_NEON_OPT=0
INCLUDEPATH += $$PWD/libpng
SOURCES += $$PWD/libpng/png.c \

View File

@ -590,7 +590,7 @@ void QCoreApplicationPrivate::initLocale()
\section1 The Event Loop and Event Handling
The event loop is started with a call to exec(). Long running
The event loop is started with a call to exec(). Long-running
operations can call processEvents() to keep the application
responsive.
@ -672,7 +672,7 @@ QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p)
#ifndef QT_NO_QOBJECT
/*!
Flushes the platform specific event queues.
Flushes the platform-specific event queues.
If you are doing graphical changes inside a loop that does not
return to the event loop on asynchronous window systems like X11
@ -690,9 +690,9 @@ void QCoreApplication::flush()
#endif
/*!
Constructs a Qt kernel application. Kernel applications are
applications without a graphical user interface. These type of
applications are used at the console or as server processes.
Constructs a Qt core application. Core applications are applications without
a graphical user interface. Such applications are used at the console or as
server processes.
The \a argc and \a argv arguments are processed by the application,
and made available in a more convenient form by the arguments()
@ -1174,7 +1174,7 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)
milliseconds or until there are no more events to process,
whichever is shorter.
You can call this function occasionally when you program is busy
You can call this function occasionally when your program is busy
doing a long operation (e.g. copying a file).
Calling this function processes events only for the calling thread.
@ -1201,9 +1201,9 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int m
*****************************************************************************/
/*!
Enters the main event loop and waits until exit() is called.
Returns the value that was set to exit() (which is 0 if exit() is
called via quit()).
Enters the main event loop and waits until exit() is called. Returns
the value that was passed to exit() (which is 0 if exit() is called via
quit()).
It is necessary to call this function to start event handling. The
main event loop receives events from the window system and
@ -1459,7 +1459,8 @@ bool QCoreApplication::compressEvent(QEvent *event, QObject *receiver, QPostEven
If \a receiver is null, the events of \a event_type are sent for all
objects. If \a event_type is 0, all the events are sent for \a receiver.
\note This method must be called from the same thread as its QObject parameter, \a receiver.
\note This method must be called from the thread in which its QObject
parameter, \a receiver, lives.
\sa flush(), postEvent()
*/
@ -1805,7 +1806,7 @@ void QCoreApplication::quit()
This signal is emitted when the application is about to quit the
main event loop, e.g. when the event loop level drops to zero.
This may happen either after a call to quit() from inside the
application or when the users shuts down the entire desktop session.
application or when the user shuts down the entire desktop session.
The signal is particularly useful if your application has to do some
last-second cleanup. Note that no user interaction is possible in
@ -2035,8 +2036,8 @@ void QCoreApplicationPrivate::setApplicationFilePath(const QString &path)
directory, and you run the \c{regexp} example, this function will
return "C:/Qt/examples/tools/regexp".
On OS X and iOS this will point to the directory actually containing the
executable, which may be inside of an application bundle (if the
On OS X and iOS this will point to the directory actually containing
the executable, which may be inside an application bundle (if the
application is bundled).
\warning On Linux, this function will try to get the path from the
@ -2604,11 +2605,11 @@ void QCoreApplication::removeLibraryPath(const QString &path)
The event filter \a filterObj receives events via its \l {QAbstractNativeEventFilter::}{nativeEventFilter()}
function, which is called for all native events received in the main thread.
The QAbstractNativeEventFilter::nativeEventFilter() function should return true if the event should
be filtered, (i.e. stopped). It should return false to allow
normal Qt processing to continue: the native event can then be translated
into a QEvent and handled by the standard Qt \l{QEvent} {event} filtering,
e.g. QObject::installEventFilter().
The QAbstractNativeEventFilter::nativeEventFilter() function should
return true if the event should be filtered, i.e. stopped. It should
return false to allow normal Qt processing to continue: the native
event can then be translated into a QEvent and handled by the standard
Qt \l{QEvent} {event} filtering, e.g. QObject::installEventFilter().
If multiple event filters are installed, the filter that was
installed last is activated first.
@ -2616,7 +2617,7 @@ void QCoreApplication::removeLibraryPath(const QString &path)
\note The filter function set here receives native messages,
i.e. MSG or XCB event structs.
\note Native event filters will be disabled when the application the
\note Native event filters will be disabled in the application when the
Qt::AA_PluginApplication attribute is set.
For maximum portability, you should always try to use QEvent
@ -2805,7 +2806,7 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc
\snippet code/src_corelib_kernel_qcoreapplication.cpp 7
The \a context parameter is normally the class name, but it can
be any string.
be any text.
\sa Q_OBJECT, QObject::tr(), QObject::trUtf8()
*/

View File

@ -251,9 +251,13 @@
// NEON intrinsics
// note: as of GCC 4.9, does not support function targets for ARM
#if defined __ARM_NEON__
#if defined(__ARM_NEON) || defined(__ARM_NEON__)
#include <arm_neon.h>
#define QT_FUNCTION_TARGET_STRING_ARM_NEON "neon"
#ifndef __ARM_NEON__
// __ARM_NEON__ is not defined on AArch64, but we need it in our NEON detection.
#define __ARM_NEON__
#endif
#endif
#undef QT_COMPILER_SUPPORTS_SIMD_ALWAYS

View File

@ -0,0 +1,59 @@
/****************************************************************************
**
** Copyright (C) 2015 Samuel Gaist <samuel.gaist@edeltech.ch>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** 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$
**
****************************************************************************/
//! [Custom Info.plist]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>png</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
</array>
</dict>
</plist>
//! [Custom Info.plist]

View File

@ -0,0 +1,73 @@
/****************************************************************************
**
** Copyright (C) 2015 Samuel Gaist <samuel.gaist@edeltech.ch>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** 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$
**
****************************************************************************/
//! [QApplication subclass]
#include <QApplication>
#include <QFileOpenEvent>
#include <QtDebug>
class MyApplication : public QApplication
{
public:
MyApplication(int &argc, char **argv)
: QApplication(argc, argv)
{
}
bool event(QEvent *event)
{
if (event->type() == QEvent::FileOpen) {
QFileOpenEvent *openEvent = static_cast<QFileOpenEvent *>(event);
qDebug() << "Open file" << openEvent->file();
}
return QApplication::event(event);
}
};
//! [QApplication subclass]
int main(int argc, char *argv[])
{
MyApplication app(argc, argv);
QPushButton closeButton("Quit");
QObject::connect(&closeButton, &QPushButton::clicked, &app, &QApplication::quit);
closeButton.show();
return app.exec();
}

View File

@ -375,7 +375,32 @@ static void convert_RGB888_to_RGB(QImageData *dest, const QImageData *src, Qt::I
}
}
#ifdef __SSE2__
extern bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionFlags);
#else
static bool convert_ARGB_to_ARGB_PM_inplace(QImageData *data,Qt::ImageConversionFlags)
{
Q_ASSERT(data->format == QImage::Format_ARGB32 || data->format == QImage::Format_RGBA8888);
const int pad = (data->bytes_per_line >> 2) - data->width;
QRgb *rgb_data = (QRgb *) data->data;
for (int i = 0; i < data->height; ++i) {
const QRgb *end = rgb_data + data->width;
while (rgb_data < end) {
*rgb_data = qPremultiply(*rgb_data);
++rgb_data;
}
rgb_data += pad;
}
if (data->format == QImage::Format_ARGB32)
data->format = QImage::Format_ARGB32_Premultiplied;
else
data->format = QImage::Format_RGBA8888_Premultiplied;
return true;
}
#endif
static void convert_ARGB_to_RGBx(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
@ -2592,7 +2617,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
#ifdef __SSE2__
convert_ARGB_to_ARGB_PM_inplace_sse2,
#else
0,
convert_ARGB_to_ARGB_PM_inplace,
#endif
0,
0,
@ -2705,12 +2730,13 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
mask_alpha_converter_rgbx_inplace,
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN && __SSE2__
0,
#ifdef __SSE2__
convert_ARGB_to_ARGB_PM_inplace_sse2,
#elif Q_BYTE_ORDER == Q_LITTLE_ENDIAN
convert_ARGB_to_ARGB_PM_inplace,
#else
0,
0,
#endif
0, 0, 0, 0, 0, 0
}, // Format_RGBA8888
@ -2921,7 +2947,7 @@ void qInitImageConversions()
}
#endif
#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64)
#if defined(__ARM_NEON__)
extern void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
qimage_converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_neon;
qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_neon;

View File

@ -35,7 +35,7 @@
#include <private/qimage_p.h>
#include <private/qsimd_p.h>
#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64)
#if defined(__ARM_NEON__)
QT_BEGIN_NAMESPACE
@ -55,6 +55,7 @@ Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, cons
if ((len - offsetToAlignOn8Bytes) >= 8) {
const quint32 *const simdEnd = end - 7;
#if !defined(Q_PROCESSOR_ARM_64)
register uint8x8_t fullVector asm ("d3") = vdup_n_u8(0xff);
do {
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
@ -76,6 +77,31 @@ Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, cons
);
#endif
} while (dst < simdEnd);
#else
register uint8x8_t fullVector asm ("v3") = vdup_n_u8(0xff);
do {
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
asm volatile (
"ld3 { v4.8b, v5.8b, v6.8b }, [%[SRC]], #24 \n\t"
"st4 { v3.8b, v4.8b, v5.8b, v6.8b }, [%[DST]], #32 \n\t"
: [DST]"+r" (dst), [SRC]"+r" (src)
: "w"(fullVector)
: "memory", "v4", "v5", "v6"
);
#else
asm volatile (
"ld3 { v0.8b, v1.8b, v2.8b }, [%[SRC]], #24 \n\t"
"mov v4.8b, v2.8b\n\t"
"mov v2.8b, v0.8b\n\t"
"mov v0.8b, v4.8b\n\t"
"st4 { v0.8b, v1.8b, v2.8b, v3.8b }, [%[DST]], #32 \n\t"
: [DST]"+r" (dst), [SRC]"+r" (src)
: "w"(fullVector)
: "memory", "v0", "v1", "v2", "v4"
);
#endif
} while (dst < simdEnd);
#endif
}
while (dst != end) {
@ -103,4 +129,4 @@ void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::I
QT_END_NAMESPACE
#endif // defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64)
#endif // defined(__ARM_NEON__)

View File

@ -978,9 +978,8 @@ extern "C" void qt_convert_rgb888_to_rgb32_mips_dspr2_asm(quint32 *dst, const uc
QJpegHandler::QJpegHandler()
: d(new QJpegHandlerPrivate(this))
{
#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64)
#if defined(__ARM_NEON__)
// from qimage_neon.cpp
if (qCpuHasFeature(NEON))
d->rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_neon;
#endif

View File

@ -43,13 +43,8 @@
#include <qvariant.h>
#include <qvector.h>
#ifdef QT_USE_BUNDLED_LIBPNG
#include <../../3rdparty/libpng/png.h>
#include <../../3rdparty/libpng/pngconf.h>
#else
#include <png.h>
#include <pngconf.h>
#endif
#if PNG_LIBPNG_VER >= 10400 && PNG_LIBPNG_VER <= 10502 \
&& defined(PNG_PEDANTIC_WARNINGS_SUPPORTED)

View File

@ -3418,6 +3418,21 @@ QShowEvent::~QShowEvent()
It may be safely ignored.
\note This class is currently supported for OS X only.
\section1 OS X Example
In order to trigger the event on OS X, the application must be configured
to let the OS know what kind of file(s) it should react on.
For example, the following \c Info.plist file declares that the application
can act as a viewer for files with a PNG extension:
\snippet qfileopenevent/Info.plist Custom Info.plist
The following implementation of a QApplication subclass prints the path to
the file that was, for example, dropped on the Dock icon of the application.
\snippet qfileopenevent/main.cpp QApplication subclass
*/
/*!

View File

@ -101,7 +101,7 @@ SSE4_1_SOURCES += painting/qdrawhelper_sse4.cpp \
painting/qimagescale_sse4.cpp
AVX2_SOURCES += painting/qdrawhelper_avx2.cpp
!ios {
!ios:!contains(QT_ARCH, "arm64") {
CONFIG += no_clang_integrated_as
NEON_SOURCES += painting/qdrawhelper_neon.cpp
NEON_HEADERS += painting/qdrawhelper_neon_p.h

View File

@ -6309,7 +6309,7 @@ void qt_memfill16(quint16 *dest, quint16 color, int count)
qt_memfill_template<quint16>(dest, color, count);
}
#endif
#if !defined(__SSE2__) && !defined(__ARM_NEON__)
#if !defined(__SSE2__) && (!defined(__ARM_NEON__) || defined(Q_PROCESSOR_ARM_64))
# ifdef QT_COMPILER_SUPPORTS_MIPS_DSP
extern "C" void qt_memfill32_asm_mips_dsp(quint32 *, quint32, int);
# endif
@ -6425,7 +6425,7 @@ void qInitDrawhelperAsm()
#endif // SSE2
#if defined(__ARM_NEON__) && !defined(Q_OS_IOS)
#if defined(__ARM_NEON__) && !defined(Q_OS_IOS) && !defined(Q_PROCESSOR_ARM_64)
qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;

View File

@ -31,15 +31,13 @@
**
****************************************************************************/
#include <private/qdrawhelper_p.h>
#include <private/qdrawhelper_neon_p.h>
#include <private/qblendfunctions_p.h>
#include <private/qmath_p.h>
#ifdef __ARM_NEON__
#include <private/qdrawhelper_neon_p.h>
#include <private/qpaintengine_raster_p.h>
#include <arm_neon.h>
QT_BEGIN_NAMESPACE

View File

@ -58,10 +58,10 @@ inline Q_DECL_CONSTEXPR int qAlpha(QRgb rgb) // get alpha part of
{ return rgb >> 24; }
inline Q_DECL_CONSTEXPR QRgb qRgb(int r, int g, int b)// set RGB value
{ return (0xffu << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff); }
{ return (0xffu << 24) | ((r & 0xffu) << 16) | ((g & 0xffu) << 8) | (b & 0xffu); }
inline Q_DECL_CONSTEXPR QRgb qRgba(int r, int g, int b, int a)// set RGBA value
{ return ((a & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff); }
{ return ((a & 0xffu) << 24) | ((r & 0xffu) << 16) | ((g & 0xffu) << 8) | (b & 0xffu); }
inline Q_DECL_CONSTEXPR int qGray(int r, int g, int b)// convert R,G,B to gray 0..255
{ return (r*11+g*16+b*5)/32; }

View File

@ -918,10 +918,11 @@ void QTextEngine::shapeLine(const QScriptLine &line)
{
QFixed x;
bool first = true;
const int end = findItem(line.from + line.length - 1);
int item = findItem(line.from);
if (item == -1)
return;
const int end = findItem(line.from + line.length - 1, item);
for ( ; item <= end; ++item) {
QScriptItem &si = layoutData->items[item];
if (si.analysis.flags == QScriptAnalysis::Tab) {
@ -1747,13 +1748,13 @@ bool QTextEngine::isRightToLeft() const
}
int QTextEngine::findItem(int strPos) const
int QTextEngine::findItem(int strPos, int firstItem) const
{
itemize();
if (strPos < 0 || strPos >= layoutData->string.size())
if (strPos < 0 || strPos >= layoutData->string.size() || firstItem < 0)
return -1;
int left = 1;
int left = firstItem + 1;
int right = layoutData->items.size()-1;
while(left <= right) {
int middle = ((right-left)/2)+left;
@ -2172,7 +2173,7 @@ void QTextEngine::justify(const QScriptLine &line)
return;
int firstItem = findItem(line.from);
int lastItem = findItem(line.from + line_length - 1);
int lastItem = findItem(line.from + line_length - 1, firstItem);
int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0;
QVarLengthArray<QJustificationPoint> justificationPoints;
@ -3529,7 +3530,7 @@ QTextLineItemIterator::QTextLineItemIterator(QTextEngine *_eng, int _lineNum, co
lineNum(_lineNum),
lineEnd(line.from + line.length),
firstItem(eng->findItem(line.from)),
lastItem(eng->findItem(lineEnd - 1)),
lastItem(eng->findItem(lineEnd - 1, firstItem)),
nItems((firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0),
logicalItem(-1),
item(-1),

View File

@ -512,7 +512,7 @@ public:
void freeMemory();
int findItem(int strPos) const;
int findItem(int strPos, int firstItem = 0) const;
inline QTextFormatCollection *formatCollection() const {
if (block.docHandle())
return block.docHandle()->formatCollection();

View File

@ -2624,26 +2624,24 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR
*/
qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
{
if (!eng->layoutData)
eng->itemize();
const QScriptLine &line = eng->lines[index];
bool lastLine = index >= eng->lines.size() - 1;
QFixed x = line.x;
x += eng->alignLine(line) - eng->leadingSpaceWidth(line);
QFixed x = line.x + eng->alignLine(line) - eng->leadingSpaceWidth(line);
if (!index && !eng->layoutData->items.size()) {
*cursorPos = 0;
if (!eng->layoutData)
eng->itemize();
if (!eng->layoutData->items.size()) {
*cursorPos = line.from;
return x.toReal();
}
int lineEnd = line.from + line.length + line.trailingSpaces;
int pos = qBound(0, *cursorPos, lineEnd);
int pos = qBound(line.from, *cursorPos, lineEnd);
int itm;
const QCharAttributes *attributes = eng->attributes();
if (!attributes) {
*cursorPos = 0;
*cursorPos = line.from;
return x.toReal();
}
while (pos < lineEnd && !attributes[pos].graphemeBoundary)
@ -2655,7 +2653,7 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
else
itm = eng->findItem(pos);
if (itm < 0) {
*cursorPos = 0;
*cursorPos = line.from;
return x.toReal();
}
eng->shapeLine(line);
@ -2663,18 +2661,14 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
const QScriptItem *si = &eng->layoutData->items[itm];
if (!si->num_glyphs)
eng->shape(itm);
pos -= si->position;
const int l = eng->length(itm);
pos = qBound(0, pos - si->position, l);
QGlyphLayout glyphs = eng->shapedGlyphs(si);
unsigned short *logClusters = eng->logClusters(si);
Q_ASSERT(logClusters);
int l = eng->length(itm);
if (pos > l)
pos = l;
if (pos < 0)
pos = 0;
int glyph_pos = pos == l ? si->num_glyphs : logClusters[pos];
if (edge == Trailing && glyph_pos < si->num_glyphs) {
// trailing edge is leading edge of next cluster
@ -2683,13 +2677,13 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
glyph_pos++;
}
bool reverse = eng->layoutData->items[itm].analysis.bidiLevel % 2;
bool reverse = si->analysis.bidiLevel % 2;
// add the items left of the cursor
int firstItem = eng->findItem(line.from);
int lastItem = eng->findItem(lineEnd - 1);
int lastItem = eng->findItem(lineEnd - 1, itm);
int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0;
QVarLengthArray<int> visualOrder(nItems);
@ -2710,13 +2704,15 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
x += si.width;
continue;
}
const int itemLength = eng->length(item);
int start = qMax(line.from, si.position);
int end = qMin(lineEnd, si.position + eng->length(item));
int end = qMin(lineEnd, si.position + itemLength);
logClusters = eng->logClusters(&si);
int gs = logClusters[start-si.position];
int ge = (end == si.position + eng->length(item)) ? si.num_glyphs-1 : logClusters[end-si.position-1];
int ge = (end == si.position + itemLength) ? si.num_glyphs-1 : logClusters[end-si.position-1];
QGlyphLayout glyphs = eng->shapedGlyphs(&si);
@ -2788,7 +2784,7 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
return line.from;
int firstItem = eng->findItem(line.from);
int lastItem = eng->findItem(line.from + line_length - 1);
int lastItem = eng->findItem(line.from + line_length - 1, firstItem);
int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0;
if (!nItems)

View File

@ -717,15 +717,19 @@ QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont
FcPatternDestroy(pattern);
if (fontSet) {
QSet<QString> duplicates;
duplicates.reserve(fontSet->nfont + 1);
duplicates.insert(family.toCaseFolded());
for (int i = 0; i < fontSet->nfont; i++) {
FcChar8 *value = 0;
if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch)
continue;
// capitalize(value);
QString familyName = QString::fromUtf8((const char *)value);
if (!fallbackFamilies.contains(familyName,Qt::CaseInsensitive) &&
familyName.compare(family, Qt::CaseInsensitive)) {
const QString familyName = QString::fromUtf8((const char *)value);
const QString familyNameCF = familyName.toCaseFolded();
if (!duplicates.contains(familyNameCF)) {
fallbackFamilies << familyName;
duplicates.insert(familyNameCF);
}
}
FcFontSetDestroy(fontSet);

View File

@ -99,6 +99,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
- (void)textInputContextKeyboardSelectionDidChangeNotification : (NSNotification *) textInputContextKeyboardSelectionDidChangeNotification;
- (void)viewDidHide;
- (void)viewDidUnhide;
- (void)removeFromSuperview;
- (BOOL)isFlipped;
- (BOOL)acceptsFirstResponder;

View File

@ -498,6 +498,12 @@ QT_WARNING_POP
m_platformWindow->exposeWindow();
}
- (void)removeFromSuperview
{
QMacAutoReleasePool pool;
[super removeFromSuperview];
}
- (void) flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset
{
m_backingStore = backingStore;

View File

@ -12,6 +12,9 @@ CONFIG += egl
LIBS += -lbcm_host
QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
# Avoid X11 header collision
DEFINES += MESA_EGL_NO_X11_HEADERS
SOURCES += $$PWD/qeglfsbrcmmain.cpp \
$$PWD/qeglfsbrcmintegration.cpp

View File

@ -89,10 +89,11 @@ QIOSIntegration::QIOSIntegration()
// Set current directory to app bundle folder
QDir::setCurrent(QString::fromUtf8([[[NSBundle mainBundle] bundlePath] UTF8String]));
UIScreen *mainScreen = [UIScreen mainScreen];
NSMutableArray *screens = [[[UIScreen screens] mutableCopy] autorelease];
if (![screens containsObject:[UIScreen mainScreen]]) {
if (![screens containsObject:mainScreen]) {
// Fallback for iOS 7.1 (QTBUG-42345)
[screens insertObject:[UIScreen mainScreen] atIndex:0];
[screens insertObject:mainScreen atIndex:0];
}
for (UIScreen *screen in screens)
@ -103,7 +104,10 @@ QIOSIntegration::QIOSIntegration()
m_touchDevice = new QTouchDevice;
m_touchDevice->setType(QTouchDevice::TouchScreen);
m_touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::NormalizedPosition);
QTouchDevice::Capabilities touchCapabilities = QTouchDevice::Position | QTouchDevice::NormalizedPosition;
if (mainScreen.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
touchCapabilities |= QTouchDevice::Pressure;
m_touchDevice->setCapabilities(touchCapabilities);
QWindowSystemInterface::registerTouchDevice(m_touchDevice);
QMacInternalPasteboardMime::initializeMimeTypes();
}

View File

@ -280,6 +280,19 @@
// -------------------------------------------------------------------------
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
{
[super traitCollectionDidChange: previousTraitCollection];
QTouchDevice *touchDevice = QIOSIntegration::instance()->touchDevice();
QTouchDevice::Capabilities touchCapabilities = touchDevice->capabilities();
if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
touchCapabilities |= QTouchDevice::Pressure;
else
touchCapabilities &= ~QTouchDevice::Pressure;
touchDevice->setCapabilities(touchCapabilities);
}
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
if (m_qioswindow->window()->flags() & Qt::WindowTransparentForInput)
@ -289,6 +302,8 @@
- (void)updateTouchList:(NSSet *)touches withState:(Qt::TouchPointState)state
{
bool supportsPressure = QIOSIntegration::instance()->touchDevice()->capabilities() & QTouchDevice::Pressure;
foreach (UITouch *uiTouch, m_activeTouches.keys()) {
QWindowSystemInterface::TouchPoint &touchPoint = m_activeTouches[uiTouch];
if (![touches containsObject:uiTouch]) {
@ -309,9 +324,17 @@
touchPoint.normalPosition = QPointF(globalScreenPosition.x() / screenSize.width(),
globalScreenPosition.y() / screenSize.height());
// We don't claim that our touch device supports QTouchDevice::Pressure,
// but fill in a meaningfull value in case clients use it anyways.
touchPoint.pressure = (state == Qt::TouchPointReleased) ? 0.0 : 1.0;
if (supportsPressure) {
// Note: iOS will deliver touchesBegan with a touch force of 0, which
// we will reflect/propagate as a 0 pressure, but there is no clear
// alternative, as we don't want to wait for a touchedMoved before
// sending a touch press event to Qt, just to have a valid pressure.
touchPoint.pressure = uiTouch.force / uiTouch.maximumPossibleForce;
} else {
// We don't claim that our touch device supports QTouchDevice::Pressure,
// but fill in a meaningfull value in case clients use it anyways.
touchPoint.pressure = (state == Qt::TouchPointReleased) ? 0.0 : 1.0;
}
}
}
}

View File

@ -49,11 +49,6 @@ QPlatformIntegration* QMirClientIntegrationPlugin::create(const QString &system,
const QStringList &)
{
if (system.toLower() == "mirclient") {
#ifdef PLATFORM_API_TOUCH
setenv("UBUNTU_PLATFORM_API_BACKEND", "touch_mirclient", 1);
#else
setenv("UBUNTU_PLATFORM_API_BACKEND", "desktop_mirclient", 1);
#endif
return new QMirClientClientIntegration;
} else {
return 0;

View File

@ -43,15 +43,17 @@
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
#include <QtGui/private/qguiapplication_p.h> // getPixmapCursor()
#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtCore/QDebug>
#include <QtCore/QScopedArrayPointer>
static void initResources()
static bool initResources()
{
#if !defined (Q_OS_WINCE) && !defined (QT_NO_IMAGEFORMAT_PNG)
Q_INIT_RESOURCE(cursors);
#endif
return true;
}
QT_BEGIN_NAMESPACE
@ -92,9 +94,14 @@ QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c)
\sa QWindowsWindowCursor
*/
HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot)
HCURSOR QWindowsCursor::createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor)
{
HCURSOR cur = 0;
scaleFactor /= pixmap.devicePixelRatioF();
if (!qFuzzyCompare(scaleFactor, 1)) {
pixmap = pixmap.scaled((scaleFactor * QSizeF(pixmap.size())).toSize(),
Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
QBitmap mask = pixmap.mask();
if (mask.isNull()) {
mask = QBitmap(pixmap.size());
@ -202,17 +209,43 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits,
}
// Create a cursor from image and mask of the format QImage::Format_Mono.
static HCURSOR createBitmapCursor(const QCursor &cursor)
static HCURSOR createBitmapCursor(const QCursor &cursor, qreal scaleFactor = 1)
{
Q_ASSERT(cursor.shape() == Qt::BitmapCursor && cursor.bitmap());
const QImage bbits = cursor.bitmap()->toImage().convertToFormat(QImage::Format_Mono);
const QImage mbits = cursor.mask()->toImage().convertToFormat(QImage::Format_Mono);
QImage bbits = cursor.bitmap()->toImage();
QImage mbits = cursor.mask()->toImage();
scaleFactor /= bbits.devicePixelRatioF();
if (!qFuzzyCompare(scaleFactor, 1)) {
const QSize scaledSize = (QSizeF(bbits.size()) * scaleFactor).toSize();
bbits = bbits.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
mbits = mbits.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
bbits = bbits.convertToFormat(QImage::Format_Mono);
mbits = mbits.convertToFormat(QImage::Format_Mono);
const bool invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1));
const bool invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1));
return createBitmapCursor(bbits, mbits, cursor.hotSpot(), invb, invm);
}
static inline QSize systemCursorSize() { return QSize(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR)); }
static QSize systemCursorSize(const QPlatformScreen *screen = Q_NULLPTR)
{
const QSize primaryScreenCursorSize(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR));
if (screen) {
// Correct the size if the DPI value of the screen differs from
// that of the primary screen.
if (const QScreen *primaryQScreen = QGuiApplication::primaryScreen()) {
const QPlatformScreen *primaryScreen = primaryQScreen->handle();
if (screen != primaryScreen) {
const qreal logicalDpi = screen->logicalDpi().first;
const qreal primaryScreenLogicalDpi = primaryScreen->logicalDpi().first;
if (!qFuzzyCompare(logicalDpi, primaryScreenLogicalDpi))
return (QSizeF(primaryScreenCursorSize) * logicalDpi / primaryScreenLogicalDpi).toSize();
}
}
}
return primaryScreenCursorSize;
}
static inline QSize standardCursorSize() { return QSize(32, 32); }
#if defined (Q_OS_WINCE) || defined (QT_NO_IMAGEFORMAT_PNG)
@ -242,7 +275,8 @@ static QWindowsCursor::PixmapCursor createPixmapCursorFromData(const QSize &syst
return QWindowsCursor::PixmapCursor(rawImage, hotSpot);
}
QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape,
const QPlatformScreen *screen)
{
// Non-standard Windows cursors are created from bitmaps
static const uchar vsplit_bits[] = {
@ -410,13 +444,13 @@ QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursor
switch (cursorShape) {
case Qt::SplitVCursor:
return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 32, vsplit_bits, vsplitm_bits);
return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 32, vsplit_bits, vsplitm_bits);
case Qt::SplitHCursor:
return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 32, hsplit_bits, hsplitm_bits);
return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 32, hsplit_bits, hsplitm_bits);
case Qt::OpenHandCursor:
return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, openhand_bits, openhandm_bits);
return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 16, openhand_bits, openhandm_bits);
case Qt::ClosedHandCursor:
return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, closedhand_bits, closedhandm_bits);
return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 16, closedhand_bits, closedhandm_bits);
case Qt::DragCopyCursor:
return QWindowsCursor::PixmapCursor(QPixmap(copyDragCursorXpmC), QPoint(0, 0));
case Qt::DragMoveCursor:
@ -436,7 +470,7 @@ struct QWindowsCustomPngCursor {
int hotSpotY;
};
QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape, const QPlatformScreen *screen)
{
static const QWindowsCustomPngCursor pngCursors[] = {
{ Qt::SplitVCursor, 32, "splitvcursor_32.png", 11, 11 },
@ -462,14 +496,14 @@ QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursor
{ Qt::DragLinkCursor, 64, "draglinkcursor_64.png", 0, 0 }
};
const int cursorSize = GetSystemMetrics(SM_CXCURSOR);
const QSize cursorSize = systemCursorSize(screen);
const QWindowsCustomPngCursor *sEnd = pngCursors + sizeof(pngCursors) / sizeof(pngCursors[0]);
const QWindowsCustomPngCursor *bestFit = 0;
int sizeDelta = INT_MAX;
for (const QWindowsCustomPngCursor *s = pngCursors; s < sEnd; ++s) {
if (s->shape != cursorShape)
continue;
const int currentSizeDelta = qMax(s->size, cursorSize) - qMin(s->size, cursorSize);
const int currentSizeDelta = qMax(s->size, cursorSize.width()) - qMin(s->size, cursorSize.width());
if (currentSizeDelta < sizeDelta) {
bestFit = s;
if (currentSizeDelta == 0)
@ -492,7 +526,7 @@ struct QWindowsStandardCursorMapping {
LPCWSTR resource;
};
HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape)
HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape, const QPlatformScreen *screen)
{
Q_ASSERT(cursorShape != Qt::BitmapCursor);
@ -515,7 +549,7 @@ HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape)
switch (cursorShape) {
case Qt::BlankCursor: {
QImage blank = QImage(systemCursorSize(), QImage::Format_Mono);
QImage blank = QImage(systemCursorSize(screen), QImage::Format_Mono);
blank.fill(0); // ignore color table
return createBitmapCursor(blank, blank);
}
@ -526,7 +560,7 @@ HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape)
case Qt::DragCopyCursor:
case Qt::DragMoveCursor:
case Qt::DragLinkCursor:
return QWindowsCursor::createPixmapCursor(customCursor(cursorShape));
return QWindowsCursor::createPixmapCursor(customCursor(cursorShape, screen));
default:
break;
}
@ -555,7 +589,7 @@ CursorHandlePtr QWindowsCursor::standardWindowCursor(Qt::CursorShape shape)
{
StandardCursorCache::Iterator it = m_standardCursorCache.find(shape);
if (it == m_standardCursorCache.end()) {
if (const HCURSOR hc = QWindowsCursor::createCursorFromShape(shape))
if (const HCURSOR hc = QWindowsCursor::createCursorFromShape(shape, m_screen))
it = m_standardCursorCache.insert(shape, CursorHandlePtr(new CursorHandle(hc)));
}
return it != m_standardCursorCache.end() ? it.value() : CursorHandlePtr(new CursorHandle);
@ -582,17 +616,21 @@ CursorHandlePtr QWindowsCursor::pixmapWindowCursor(const QCursor &c)
++it;
}
}
const qreal scaleFactor = QHighDpiScaling::factor(m_screen);
const QPixmap pixmap = c.pixmap();
const HCURSOR hc = pixmap.isNull()
? createBitmapCursor(c) : QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot());
? createBitmapCursor(c, scaleFactor)
: QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot(), scaleFactor);
it = m_pixmapCursorCache.insert(cacheKey, CursorHandlePtr(new CursorHandle(hc)));
}
return it.value();
}
QWindowsCursor::QWindowsCursor()
QWindowsCursor::QWindowsCursor(const QPlatformScreen *screen)
: m_screen(screen)
{
initResources();
static const bool dummy = initResources();
Q_UNUSED(dummy)
}
/*!
@ -654,6 +692,94 @@ void QWindowsCursor::setPos(const QPoint &pos)
SetCursorPos(pos.x() , pos.y());
}
QPixmap QWindowsCursor::dragDefaultCursor(Qt::DropAction action) const
{
switch (action) {
case Qt::CopyAction:
if (m_copyDragCursor.isNull())
m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor, m_screen).pixmap;
return m_copyDragCursor;
case Qt::TargetMoveAction:
case Qt::MoveAction:
if (m_moveDragCursor.isNull())
m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor, m_screen).pixmap;
return m_moveDragCursor;
case Qt::LinkAction:
if (m_linkDragCursor.isNull())
m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor, m_screen).pixmap;
return m_linkDragCursor;
default:
break;
}
static const char * const ignoreDragCursorXpmC[] = {
"24 30 3 1",
". c None",
"a c #000000",
"X c #FFFFFF",
"aa......................",
"aXa.....................",
"aXXa....................",
"aXXXa...................",
"aXXXXa..................",
"aXXXXXa.................",
"aXXXXXXa................",
"aXXXXXXXa...............",
"aXXXXXXXXa..............",
"aXXXXXXXXXa.............",
"aXXXXXXaaaa.............",
"aXXXaXXa................",
"aXXaaXXa................",
"aXa..aXXa...............",
"aa...aXXa...............",
"a.....aXXa..............",
"......aXXa.....XXXX.....",
".......aXXa..XXaaaaXX...",
".......aXXa.XaaaaaaaaX..",
"........aa.XaaaXXXXaaaX.",
"...........XaaaaX..XaaX.",
"..........XaaXaaaX..XaaX",
"..........XaaXXaaaX.XaaX",
"..........XaaX.XaaaXXaaX",
"..........XaaX..XaaaXaaX",
"...........XaaX..XaaaaX.",
"...........XaaaXXXXaaaX.",
"............XaaaaaaaaX..",
".............XXaaaaXX...",
"...............XXXX....."};
if (m_ignoreDragCursor.isNull()) {
#if !defined (Q_OS_WINCE)
HCURSOR cursor = LoadCursor(NULL, IDC_NO);
ICONINFO iconInfo = {0, 0, 0, 0, 0};
GetIconInfo(cursor, &iconInfo);
BITMAP bmColor = {0, 0, 0, 0, 0, 0, 0};
if (iconInfo.hbmColor
&& GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bmColor)
&& bmColor.bmWidth == bmColor.bmWidthBytes / 4) {
const int colorBitsLength = bmColor.bmHeight * bmColor.bmWidthBytes;
uchar *colorBits = new uchar[colorBitsLength];
GetBitmapBits(iconInfo.hbmColor, colorBitsLength, colorBits);
const QImage colorImage(colorBits, bmColor.bmWidth, bmColor.bmHeight,
bmColor.bmWidthBytes, QImage::Format_ARGB32);
m_ignoreDragCursor = QPixmap::fromImage(colorImage);
delete [] colorBits;
} else {
m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC);
}
DeleteObject(iconInfo.hbmMask);
DeleteObject(iconInfo.hbmColor);
DestroyCursor(cursor);
#else // !Q_OS_WINCE
m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC);
#endif // !Q_OS_WINCE
}
return m_ignoreDragCursor;
}
/*!
\class QWindowsWindowCursor
\brief Per-Window cursor. Contains a QCursor and manages its associated system

View File

@ -96,29 +96,37 @@ public:
QPoint hotSpot;
};
QWindowsCursor();
explicit QWindowsCursor(const QPlatformScreen *screen);
void changeCursor(QCursor * widgetCursor, QWindow * widget) Q_DECL_OVERRIDE;
QPoint pos() const Q_DECL_OVERRIDE;
void setPos(const QPoint &pos) Q_DECL_OVERRIDE;
static HCURSOR createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot);
static HCURSOR createPixmapCursor(const PixmapCursor &pc) { return createPixmapCursor(pc.pixmap, pc.hotSpot); }
static PixmapCursor customCursor(Qt::CursorShape cursorShape);
static HCURSOR createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor = 1);
static HCURSOR createPixmapCursor(const PixmapCursor &pc, qreal scaleFactor = 1) { return createPixmapCursor(pc.pixmap, pc.hotSpot, scaleFactor); }
static PixmapCursor customCursor(Qt::CursorShape cursorShape, const QPlatformScreen *screen = Q_NULLPTR);
static HCURSOR createCursorFromShape(Qt::CursorShape cursorShape);
static HCURSOR createCursorFromShape(Qt::CursorShape cursorShape, const QPlatformScreen *screen = Q_NULLPTR);
static QPoint mousePosition();
static CursorState cursorState();
CursorHandlePtr standardWindowCursor(Qt::CursorShape s = Qt::ArrowCursor);
CursorHandlePtr pixmapWindowCursor(const QCursor &c);
QPixmap dragDefaultCursor(Qt::DropAction action) const;
private:
typedef QHash<Qt::CursorShape, CursorHandlePtr> StandardCursorCache;
typedef QHash<QWindowsPixmapCursorCacheKey, CursorHandlePtr> PixmapCursorCache;
const QPlatformScreen *const m_screen;
StandardCursorCache m_standardCursorCache;
PixmapCursorCache m_pixmapCursorCache;
mutable QPixmap m_copyDragCursor;
mutable QPixmap m_moveDragCursor;
mutable QPixmap m_linkDragCursor;
mutable QPixmap m_ignoreDragCursor;
};
QT_END_NAMESPACE

View File

@ -269,13 +269,6 @@ QDebug operator<<(QDebug d, const QWindowsOleDropSource::CursorEntry &e)
}
#endif // !QT_NO_DEBUG_STREAM
static qreal dragScaleFactor()
{
const QWindowsScreenManager &screenManager = QWindowsContext::instance()->screenManager();
const QWindowsScreen *screen = screenManager.screenAtDp(QWindowsCursor::mousePosition());
return screen ? QHighDpiScaling::factor(screen) : qreal(1);
}
/*!
\brief Blend custom pixmap with cursors.
*/
@ -286,7 +279,17 @@ void QWindowsOleDropSource::createCursors()
const QPixmap pixmap = drag->pixmap();
const bool hasPixmap = !pixmap.isNull();
const qreal scaleFactor = dragScaleFactor();
// Find screen for drag. Could be obtained from QDrag::source(), but that might be a QWidget.
qreal scaleFactor = 1;
QPlatformCursor *platformCursor = Q_NULLPTR;
if (const QPlatformScreen *platformScreen = QWindowsContext::instance()->screenManager().screenAtDp(QWindowsCursor::mousePosition())) {
scaleFactor = QHighDpiScaling::factor(platformScreen);
platformCursor = platformScreen->cursor();
}
if (!platformCursor && QGuiApplication::primaryScreen())
platformCursor = QGuiApplication::primaryScreen()->handle()->cursor();
const bool scalePixmap = hasPixmap
&& m_mode != TouchDrag // Touch drag: pixmap is shown in a separate QWindow, which will be scaled.
&& (scaleFactor != 1 && scaleFactor != qRound(pixmap.devicePixelRatio()));
@ -304,8 +307,8 @@ void QWindowsOleDropSource::createCursors()
for (int cnum = 0; cnum < actionCount; ++cnum) {
const Qt::DropAction action = actions[cnum];
QPixmap cursorPixmap = drag->dragCursor(action);
if (cursorPixmap.isNull())
cursorPixmap = m_drag->defaultCursor(action);
if (cursorPixmap.isNull() && platformCursor)
cursorPixmap = static_cast<QWindowsCursor *>(platformCursor)->dragDefaultCursor(action);
const qint64 cacheKey = cursorPixmap.cacheKey();
const auto it = m_cursors.find(action);
if (it != m_cursors.end() && it.value().cacheKey == cacheKey)
@ -704,94 +707,6 @@ IDropTargetHelper* QWindowsDrag::dropHelper() {
return m_cachedDropTargetHelper;
}
QPixmap QWindowsDrag::defaultCursor(Qt::DropAction action) const
{
switch (action) {
case Qt::CopyAction:
if (m_copyDragCursor.isNull())
m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor).pixmap;
return m_copyDragCursor;
case Qt::TargetMoveAction:
case Qt::MoveAction:
if (m_moveDragCursor.isNull())
m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor).pixmap;
return m_moveDragCursor;
case Qt::LinkAction:
if (m_linkDragCursor.isNull())
m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor).pixmap;
return m_linkDragCursor;
default:
break;
}
static const char * const ignoreDragCursorXpmC[] = {
"24 30 3 1",
". c None",
"a c #000000",
"X c #FFFFFF",
"aa......................",
"aXa.....................",
"aXXa....................",
"aXXXa...................",
"aXXXXa..................",
"aXXXXXa.................",
"aXXXXXXa................",
"aXXXXXXXa...............",
"aXXXXXXXXa..............",
"aXXXXXXXXXa.............",
"aXXXXXXaaaa.............",
"aXXXaXXa................",
"aXXaaXXa................",
"aXa..aXXa...............",
"aa...aXXa...............",
"a.....aXXa..............",
"......aXXa.....XXXX.....",
".......aXXa..XXaaaaXX...",
".......aXXa.XaaaaaaaaX..",
"........aa.XaaaXXXXaaaX.",
"...........XaaaaX..XaaX.",
"..........XaaXaaaX..XaaX",
"..........XaaXXaaaX.XaaX",
"..........XaaX.XaaaXXaaX",
"..........XaaX..XaaaXaaX",
"...........XaaX..XaaaaX.",
"...........XaaaXXXXaaaX.",
"............XaaaaaaaaX..",
".............XXaaaaXX...",
"...............XXXX....."};
if (m_ignoreDragCursor.isNull()) {
#if !defined (Q_OS_WINCE)
HCURSOR cursor = LoadCursor(NULL, IDC_NO);
ICONINFO iconInfo = {0, 0, 0, 0, 0};
GetIconInfo(cursor, &iconInfo);
BITMAP bmColor = {0, 0, 0, 0, 0, 0, 0};
if (iconInfo.hbmColor
&& GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bmColor)
&& bmColor.bmWidth == bmColor.bmWidthBytes / 4) {
const int colorBitsLength = bmColor.bmHeight * bmColor.bmWidthBytes;
uchar *colorBits = new uchar[colorBitsLength];
GetBitmapBits(iconInfo.hbmColor, colorBitsLength, colorBits);
const QImage colorImage(colorBits, bmColor.bmWidth, bmColor.bmHeight,
bmColor.bmWidthBytes, QImage::Format_ARGB32);
m_ignoreDragCursor = QPixmap::fromImage(colorImage);
delete [] colorBits;
} else {
m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC);
}
DeleteObject(iconInfo.hbmMask);
DeleteObject(iconInfo.hbmColor);
DestroyCursor(cursor);
#else // !Q_OS_WINCE
m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC);
#endif // !Q_OS_WINCE
}
return m_ignoreDragCursor;
}
Qt::DropAction QWindowsDrag::drag(QDrag *drag)
{
// TODO: Accessibility handling?

View File

@ -42,6 +42,9 @@
struct IDropTargetHelper;
QT_BEGIN_NAMESPACE
class QPlatformScreen;
class QWindowsDropMimeData : public QWindowsInternalMimeData {
public:
QWindowsDropMimeData() {}
@ -97,8 +100,6 @@ public:
IDropTargetHelper* dropHelper();
QPixmap defaultCursor(Qt::DropAction action) const;
private:
static bool m_canceled;
@ -106,11 +107,6 @@ private:
IDataObject *m_dropDataObject;
IDropTargetHelper* m_cachedDropTargetHelper;
mutable QPixmap m_copyDragCursor;
mutable QPixmap m_moveDragCursor;
mutable QPixmap m_linkDragCursor;
mutable QPixmap m_ignoreDragCursor;
};
QT_END_NAMESPACE

View File

@ -195,16 +195,6 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d)
}
#endif // !QT_NO_DEBUG_STREAM
// Return the cursor to be shared by all screens (virtual desktop).
static inline QSharedPointer<QPlatformCursor> sharedCursor()
{
#ifndef QT_NO_CURSOR
if (const QScreen *primaryScreen = QGuiApplication::primaryScreen())
return static_cast<const QWindowsScreen *>(primaryScreen->handle())->cursorPtr();
#endif
return QSharedPointer<QPlatformCursor>(new QWindowsCursor);
}
/*!
\class QWindowsScreen
\brief Windows screen.
@ -216,7 +206,7 @@ static inline QSharedPointer<QPlatformCursor> sharedCursor()
QWindowsScreen::QWindowsScreen(const QWindowsScreenData &data) :
m_data(data)
#ifndef QT_NO_CURSOR
,m_cursor(sharedCursor())
, m_cursor(new QWindowsCursor(this))
#endif
{
}

View File

@ -42,7 +42,7 @@
#include <QtCore/QList>
#include <QtCore/QVector>
#include <QtCore/QPair>
#include <QtCore/QSharedPointer>
#include <QtCore/QScopedPointer>
#include <qpa/qplatformscreen.h>
QT_BEGIN_NAMESPACE
@ -74,7 +74,7 @@ class QWindowsScreen : public QPlatformScreen
{
public:
#ifndef QT_NO_CURSOR
typedef QSharedPointer<QPlatformCursor> CursorPtr;
typedef QScopedPointer<QPlatformCursor> CursorPtr;
#endif
explicit QWindowsScreen(const QWindowsScreenData &data);

View File

@ -507,6 +507,8 @@ QWinRTScreen::QWinRTScreen()
hr = d->displayInformation->get_NativeOrientation(&displayOrientation);
Q_ASSERT_SUCCEEDED(hr);
d->nativeOrientation = static_cast<Qt::ScreenOrientation>(static_cast<int>(qtOrientationsFromNative(displayOrientation)));
// Set initial pixel density
onDpiChanged(Q_NULLPTR, Q_NULLPTR);
d->orientation = d->nativeOrientation;
ComPtr<IApplicationViewStatics2> applicationViewStatics;
@ -753,7 +755,6 @@ void QWinRTScreen::initialize()
Q_ASSERT_SUCCEEDED(hr);
hr = d->displayInformation->add_DpiChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onDpiChanged).Get(), &d->displayTokens[&IDisplayInformation::remove_DpiChanged]);
Q_ASSERT_SUCCEEDED(hr);
onDpiChanged(Q_NULLPTR, Q_NULLPTR);
onOrientationChanged(Q_NULLPTR, Q_NULLPTR);
onVisibilityChanged(nullptr, nullptr);
}

View File

@ -1086,8 +1086,12 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
case XCB_FOCUS_OUT:
HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent);
case XCB_KEY_PRESS:
m_keyboard->updateXKBStateFromCore(((xcb_key_press_event_t *)event)->state);
{
xcb_key_press_event_t *kp = (xcb_key_press_event_t *)event;
m_keyboard->updateXKBStateFromCore(kp->state);
setTime(kp->time);
HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent);
}
case XCB_KEY_RELEASE:
m_keyboard->updateXKBStateFromCore(((xcb_key_release_event_t *)event)->state);
HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent);

View File

@ -556,7 +556,8 @@ void QXcbScreen::updateRefreshRate(xcb_randr_mode_t mode)
for (; modesIter.rem; xcb_randr_mode_info_next(&modesIter)) {
xcb_randr_mode_info_t *modeInfo = modesIter.data;
if (modeInfo->id == mode) {
m_refreshRate = modeInfo->dot_clock / (modeInfo->htotal * modeInfo->vtotal);
const uint32_t dotCount = modeInfo->htotal * modeInfo->vtotal;
m_refreshRate = (dotCount != 0) ? modeInfo->dot_clock / dotCount : 0;
m_mode = mode;
break;
}

View File

@ -314,8 +314,6 @@ void QXcbWindow::create()
destroy();
m_deferredExpose = false;
m_configureNotifyPending = true;
m_windowState = Qt::WindowNoState;
Qt::WindowType type = window()->type();
@ -2032,12 +2030,8 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
if (newScreen != currentScreen)
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
m_configureNotifyPending = false;
if (m_deferredExpose) {
m_deferredExpose = false;
if (m_mapped)
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
}
if (m_usingSyncProtocol && m_syncState == SyncReceived)
m_syncState = SyncAndConfigureReceived;
@ -2104,10 +2098,8 @@ void QXcbWindow::handleMapNotifyEvent(const xcb_map_notify_event_t *event)
m_mapped = true;
if (m_deferredActivation)
requestActivateWindow();
if (m_configureNotifyPending)
m_deferredExpose = true;
else
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
}
}

View File

@ -232,8 +232,6 @@ protected:
bool m_transparent;
bool m_usingSyncProtocol;
bool m_deferredActivation;
bool m_deferredExpose;
bool m_configureNotifyPending;
bool m_embedded;
bool m_alertState;
xcb_window_t m_netWmUserTimeWindow;

View File

@ -175,8 +175,11 @@ private:
tp = QMetaType::UnknownType;
}
if (tp == QMetaType::UnknownType) {
qWarning("Don't know how to handle '%s', use qRegisterMetaType to register it.",
member.parameterNames().at(i).constData());
qWarning("QSignalSpy: Unable to handle parameter '%s' of type '%s' of method '%s',"
" use qRegisterMetaType to register it.",
member.parameterNames().at(i).constData(),
member.parameterTypes().at(i).constData(),
member.name().constData());
}
args << tp;
}

View File

@ -1172,8 +1172,7 @@ void QOpenGLWidget::resizeEvent(QResizeEvent *e)
d->recreateFbo();
resizeGL(width(), height());
d->invokeUserPaint();
d->resolveSamples();
d->sendPaintEvent(QRect(QPoint(0, 0), size()));
}
/*!

View File

@ -271,6 +271,9 @@ QWidgetPrivate::QWidgetPrivate(int version)
#ifndef QT_NO_IM
, inheritsInputMethodHints(0)
#endif
#ifndef QT_NO_OPENGL
, renderToTextureReallyDirty(1)
#endif
#if defined(Q_OS_WIN)
, noPaintOnScreen(0)
#endif
@ -5560,7 +5563,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
<< "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
#endif
bool grabbed = false;
bool skipPaintEvent = false;
#ifndef QT_NO_OPENGL
if (renderToTexture) {
// This widget renders into a texture which is composed later. We just need to
@ -5574,14 +5577,18 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
} else {
// We are not drawing to a backingstore: fall back to QImage
p.drawImage(q->rect(), grabFramebuffer());
grabbed = true;
skipPaintEvent = true;
}
endBackingStorePainting();
}
if (renderToTextureReallyDirty)
renderToTextureReallyDirty = 0;
else
skipPaintEvent = true;
}
#endif // QT_NO_OPENGL
if (!grabbed) {
if (!skipPaintEvent) {
//actually send the paint event
sendPaintEvent(toBePainted);
}

View File

@ -743,6 +743,9 @@ public:
#ifndef QT_NO_IM
uint inheritsInputMethodHints : 1;
#endif
#ifndef QT_NO_OPENGL
uint renderToTextureReallyDirty : 1;
#endif
// *************************** Platform specific ************************************
#if defined(Q_OS_WIN)

View File

@ -1000,6 +1000,16 @@ void QPlatformTextureListWatcher::onLockStatusChanged(bool locked)
if (!isLocked())
m_backingStore->sync();
}
#else
static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget)
{
Q_UNUSED(tlw);
Q_UNUSED(widget);
return Q_NULLPTR;
}
#endif // QT_NO_OPENGL
static inline bool discardSyncRequest(QWidget *tlw, QTLWExtra *tlwExtra)
@ -1220,6 +1230,9 @@ void QWidgetBackingStore::doSync()
QWidget *w = static_cast<QWidget *>(tl->source(i));
if (dirtyRenderToTextureWidgets.contains(w)) {
const QRect rect = tl->geometry(i); // mapped to the tlw already
// Set a flag to indicate that the paint event for this
// render-to-texture widget must not to be optimized away.
w->d_func()->renderToTextureReallyDirty = 1;
dirty += rect;
toClean += rect;
}

View File

@ -284,12 +284,6 @@ bool QSystemTrayIcon::isVisible() const
*/
bool QSystemTrayIcon::event(QEvent *e)
{
#if defined(Q_DEAD_CODE_FROM_QT4_X11)
if (e->type() == QEvent::ToolTip) {
Q_D(QSystemTrayIcon);
return d->sys->deliverToolTipEvent(e);
}
#endif
return QObject::event(e);
}

View File

@ -196,6 +196,9 @@ void QSystemTrayIconSys::mouseDoubleClickEvent(QMouseEvent *ev)
bool QSystemTrayIconSys::event(QEvent *e)
{
switch (e->type()) {
case QEvent::ToolTip:
QApplication::sendEvent(q, e);
break;
#ifndef QT_NO_WHEELEVENT
case QEvent::Wheel:
return QApplication::sendEvent(q, e);

View File

@ -38,6 +38,7 @@
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QThread>
#include <QtCore/QTemporaryDir>
#include <QtCore/QRegExp>
#include <QtCore/QDebug>
#include <QtCore/QMetaType>
@ -54,14 +55,6 @@ Q_DECLARE_METATYPE(QProcess::ExitStatus);
Q_DECLARE_METATYPE(QProcess::ProcessState);
#endif
#define QPROCESS_VERIFY(Process, Fn) \
{ \
const bool ret = Process.Fn; \
if (ret == false) \
qWarning("QProcess error: %d: %s", Process.error(), qPrintable(Process.errorString())); \
QVERIFY(ret); \
}
typedef void (QProcess::*QProcessFinishedSignal1)(int);
typedef void (QProcess::*QProcessFinishedSignal2)(int, QProcess::ExitStatus);
typedef void (QProcess::*QProcessErrorSignal)(QProcess::ProcessError);
@ -180,6 +173,7 @@ protected slots:
private:
qint64 bytesAvailable;
QTemporaryDir m_temporaryDir;
#endif //QT_NO_PROCESS
};
@ -188,6 +182,7 @@ void tst_QProcess::initTestCase()
#ifdef QT_NO_PROCESS
QSKIP("This test requires QProcess support");
#else
QVERIFY2(m_temporaryDir.isValid(), qPrintable(m_temporaryDir.errorString()));
// chdir to our testdata path and execute helper apps relative to that.
QString testdata_dir = QFileInfo(QFINDTESTDATA("testProcessNormal")).absolutePath();
QVERIFY2(QDir::setCurrent(testdata_dir), qPrintable("Could not chdir to " + testdata_dir));
@ -1717,7 +1712,7 @@ void tst_QProcess::failToStartEmptyArgs()
// Reading and writing to a process is not supported on Qt/CE
void tst_QProcess::removeFileWhileProcessIsRunning()
{
QFile file("removeFile.txt");
QFile file(m_temporaryDir.path() + QLatin1String("/removeFile.txt"));
QVERIFY(file.open(QFile::WriteOnly));
QProcess process;
@ -1948,16 +1943,16 @@ void tst_QProcess::setStandardInputFile()
{
static const char data[] = "A bunch\1of\2data\3\4\5\6\7...";
QProcess process;
QFile file("data");
QFile file(m_temporaryDir.path() + QLatin1String("/data-sif"));
QVERIFY(file.open(QIODevice::WriteOnly));
file.write(data, sizeof data);
file.close();
process.setStandardInputFile("data");
process.setStandardInputFile(file.fileName());
process.start("testProcessEcho/testProcessEcho");
QPROCESS_VERIFY(process, waitForFinished());
QVERIFY(process.waitForFinished());
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
QCOMPARE(process.exitCode(), 0);
QByteArray all = process.readAll();
@ -1967,7 +1962,7 @@ void tst_QProcess::setStandardInputFile()
QProcess process2;
process2.setStandardInputFile(QProcess::nullDevice());
process2.start("testProcessEcho/testProcessEcho");
QPROCESS_VERIFY(process2, waitForFinished());
QVERIFY(process2.waitForFinished());
all = process2.readAll();
QCOMPARE(all.size(), 0);
}
@ -2016,7 +2011,7 @@ void tst_QProcess::setStandardOutputFile()
QIODevice::OpenMode mode = append ? QIODevice::Append : QIODevice::Truncate;
// create the destination file with data
QFile file("data");
QFile file(m_temporaryDir.path() + QLatin1String("/data-stdof-") + QLatin1String(QTest::currentDataTag()));
QVERIFY(file.open(QIODevice::WriteOnly));
file.write(data, sizeof data - 1);
file.close();
@ -2025,13 +2020,13 @@ void tst_QProcess::setStandardOutputFile()
QProcess process;
process.setReadChannelMode(channelMode);
if (channelToTest == QProcess::StandardOutput)
process.setStandardOutputFile("data", mode);
process.setStandardOutputFile(file.fileName(), mode);
else
process.setStandardErrorFile("data", mode);
process.setStandardErrorFile(file.fileName(), mode);
process.start("testProcessEcho2/testProcessEcho2");
process.write(testdata, sizeof testdata);
QPROCESS_VERIFY(process,waitForFinished());
QVERIFY(process.waitForFinished());
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
QCOMPARE(process.exitCode(), 0);
@ -2062,7 +2057,7 @@ void tst_QProcess::setStandardOutputFileNullDevice()
process.setStandardOutputFile(QProcess::nullDevice());
process.start("testProcessEcho2/testProcessEcho2");
process.write(testdata, sizeof testdata);
QPROCESS_VERIFY(process,waitForFinished());
QVERIFY(process.waitForFinished());
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
QCOMPARE(process.exitCode(), 0);
QCOMPARE(process.bytesAvailable(), Q_INT64_C(0));
@ -2074,13 +2069,14 @@ void tst_QProcess::setStandardOutputFileAndWaitForBytesWritten()
{
static const char testdata[] = "Test data.";
QFile file("data");
QFile file(m_temporaryDir.path() + QLatin1String("/data-stdofawfbw"));
QProcess process;
process.setStandardOutputFile(file.fileName());
process.start("testProcessEcho2/testProcessEcho2");
QVERIFY2(process.waitForStarted(), qPrintable(process.errorString()));
process.write(testdata, sizeof testdata);
process.waitForBytesWritten();
QPROCESS_VERIFY(process, waitForFinished());
QVERIFY(process.waitForFinished());
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
QCOMPARE(process.exitCode(), 0);
@ -2122,10 +2118,10 @@ void tst_QProcess::setStandardOutputProcess()
if (waitForBytesWritten)
source.waitForBytesWritten();
source.closeWriteChannel();
QPROCESS_VERIFY(source, waitForFinished());
QVERIFY(source.waitForFinished());
QCOMPARE(source.exitStatus(), QProcess::NormalExit);
QCOMPARE(source.exitCode(), 0);
QPROCESS_VERIFY(sink, waitForFinished());
QVERIFY(sink.waitForFinished());
QCOMPARE(sink.exitStatus(), QProcess::NormalExit);
QCOMPARE(sink.exitCode(), 0);
QByteArray all = sink.readAll();
@ -2151,14 +2147,15 @@ void tst_QProcess::fileWriterProcess()
QTime stopWatch;
stopWatch.start();
const QString fileName = QLatin1String("fileWriterProcess.txt");
const QString fileName = m_temporaryDir.path() + QLatin1String("/fileWriterProcess.txt");
const QString binary = QDir::currentPath() + QLatin1String("/fileWriterProcess/fileWriterProcess");
do {
if (QFile::exists(fileName))
QVERIFY(QFile::remove(fileName));
QProcess process;
process.start("fileWriterProcess/fileWriterProcess",
QIODevice::ReadWrite | QIODevice::Text);
process.setWorkingDirectory(m_temporaryDir.path());
process.start(binary, QIODevice::ReadWrite | QIODevice::Text);
process.write(stdinStr);
process.closeWriteChannel();
while (process.bytesToWrite()) {
@ -2181,8 +2178,9 @@ void tst_QProcess::detachedWorkingDirectoryAndPid()
QTest::qSleep(1000);
#endif
QFile infoFile(QDir::currentPath() + QLatin1String("/detachedinfo.txt"));
infoFile.remove();
QFile infoFile(m_temporaryDir.path() + QLatin1String("/detachedinfo.txt"));
if (infoFile.exists())
QVERIFY(infoFile.remove());
QString workingDir = QDir::currentPath() + "/testDetached";

View File

@ -49,6 +49,9 @@ class tst_QItemModel : public QObject
{
Q_OBJECT
public:
tst_QItemModel();
public slots:
void init();
void cleanup();
@ -124,6 +127,11 @@ private:
bool insertRecursively;
};
tst_QItemModel::tst_QItemModel()
{
qRegisterMetaType<QAbstractItemModel::LayoutChangeHint>();
}
void tst_QItemModel::init()
{
testModels = new ModelsToTest();

View File

@ -33,6 +33,7 @@
#include <QtTest/QtTest>
#include <qatomic.h>
#include <qcoreapplication.h>
#include <qmutex.h>
#include <qthread.h>
@ -54,7 +55,25 @@ private slots:
static const int iterations = 4;
static const int ThreadCount = 4;
class wait_QMutex_Thread_1 : public QThread
// Terminate thread in destructor for threads instantiated on the stack
class TerminatingThread : public QThread
{
public:
explicit TerminatingThread()
{
setTerminationEnabled(true);
}
~TerminatingThread()
{
if (isRunning()) {
qWarning() << "forcibly terminating " << objectName();
terminate();
}
}
};
class wait_QMutex_Thread_1 : public TerminatingThread
{
public:
QMutex mutex;
@ -72,7 +91,7 @@ public:
}
};
class wait_QMutex_Thread_2 : public QThread
class wait_QMutex_Thread_2 : public TerminatingThread
{
public:
QWaitCondition started;
@ -93,7 +112,7 @@ public:
}
};
class wait_QReadWriteLock_Thread_1 : public QThread
class wait_QReadWriteLock_Thread_1 : public TerminatingThread
{
public:
QReadWriteLock readWriteLock;
@ -111,7 +130,7 @@ public:
}
};
class wait_QReadWriteLock_Thread_2 : public QThread
class wait_QReadWriteLock_Thread_2 : public TerminatingThread
{
public:
QWaitCondition started;
@ -155,7 +174,11 @@ void tst_QWaitCondition::wait_QMutex()
// test multiple threads waiting on separate wait conditions
wait_QMutex_Thread_1 thread[ThreadCount];
const QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_mutex_")
+ QString::number(i) + QLatin1Char('_');
for (x = 0; x < ThreadCount; ++x) {
thread[x].setObjectName(prefix + QString::number(x));
thread[x].mutex.lock();
thread[x].start();
// wait for thread to start
@ -185,8 +208,12 @@ void tst_QWaitCondition::wait_QMutex()
QWaitCondition cond1, cond2;
wait_QMutex_Thread_2 thread[ThreadCount];
const QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_mutex_")
+ QString::number(i) + QLatin1Char('_');
mutex.lock();
for (x = 0; x < ThreadCount; ++x) {
thread[x].setObjectName(prefix + QString::number(x));
thread[x].mutex = &mutex;
thread[x].cond = (x < ThreadCount / 2) ? &cond1 : &cond2;
thread[x].start();
@ -289,7 +316,10 @@ void tst_QWaitCondition::wait_QReadWriteLock()
// test multiple threads waiting on separate wait conditions
wait_QReadWriteLock_Thread_1 thread[ThreadCount];
const QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_lockforread_");
for (x = 0; x < ThreadCount; ++x) {
thread[x].setObjectName(prefix + QString::number(x));
thread[x].readWriteLock.lockForRead();
thread[x].start();
// wait for thread to start
@ -319,8 +349,11 @@ void tst_QWaitCondition::wait_QReadWriteLock()
QWaitCondition cond1, cond2;
wait_QReadWriteLock_Thread_2 thread[ThreadCount];
const QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_lockforwrite_");
readWriteLock.lockForWrite();
for (x = 0; x < ThreadCount; ++x) {
thread[x].setObjectName(prefix + QString::number(x));
thread[x].readWriteLock = &readWriteLock;
thread[x].cond = (x < ThreadCount / 2) ? &cond1 : &cond2;
thread[x].start();
@ -346,11 +379,17 @@ void tst_QWaitCondition::wait_QReadWriteLock()
}
}
class wake_Thread : public QThread
class WakeThreadBase : public TerminatingThread
{
public:
static int count;
QAtomicInt *count;
WakeThreadBase() : count(Q_NULLPTR) {}
};
class wake_Thread : public WakeThreadBase
{
public:
QWaitCondition started;
QWaitCondition dummy;
@ -366,24 +405,23 @@ public:
void run()
{
Q_ASSERT(count);
Q_ASSERT(mutex);
Q_ASSERT(cond);
mutex->lock();
++count;
++*count;
dummy.wakeOne(); // this wakeup should be lost
started.wakeOne();
dummy.wakeAll(); // this one too
cond->wait(mutex);
--count;
--*count;
mutex->unlock();
}
};
int wake_Thread::count = 0;
class wake_Thread_2 : public QThread
class wake_Thread_2 : public WakeThreadBase
{
public:
static int count;
QWaitCondition started;
QWaitCondition dummy;
@ -399,22 +437,27 @@ public:
void run()
{
Q_ASSERT(count);
Q_ASSERT(readWriteLock);
Q_ASSERT(cond);
readWriteLock->lockForWrite();
++count;
++*count;
dummy.wakeOne(); // this wakeup should be lost
started.wakeOne();
dummy.wakeAll(); // this one too
cond->wait(readWriteLock);
--count;
--*count;
readWriteLock->unlock();
}
};
int wake_Thread_2::count = 0;
void tst_QWaitCondition::wakeOne()
{
static const int firstWaitInterval = 1000;
static const int waitInterval = 30;
int x;
QAtomicInt count;
// wake up threads, one at a time
for (int i = 0; i < iterations; ++i) {
QMutex mutex;
@ -424,8 +467,13 @@ void tst_QWaitCondition::wakeOne()
wake_Thread thread[ThreadCount];
bool thread_exited[ThreadCount];
QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_mutex_")
+ QString::number(i) + QLatin1Char('_');
mutex.lock();
for (x = 0; x < ThreadCount; ++x) {
thread[x].setObjectName(prefix + QString::number(x));
thread[x].count = &count;
thread[x].mutex = &mutex;
thread[x].cond = &cond;
thread_exited[x] = false;
@ -438,7 +486,7 @@ void tst_QWaitCondition::wakeOne()
}
mutex.unlock();
QCOMPARE(wake_Thread::count, ThreadCount);
QCOMPARE(count.load(), ThreadCount);
// wake up threads one at a time
for (x = 0; x < ThreadCount; ++x) {
@ -452,24 +500,29 @@ void tst_QWaitCondition::wakeOne()
for (int y = 0; y < ThreadCount; ++y) {
if (thread_exited[y])
continue;
if (thread[y].wait(exited > 0 ? 10 : 1000)) {
if (thread[y].wait(exited > 0 ? waitInterval : firstWaitInterval)) {
thread_exited[y] = true;
++exited;
}
}
QCOMPARE(exited, 1);
QCOMPARE(wake_Thread::count, ThreadCount - (x + 1));
QCOMPARE(count.load(), ThreadCount - (x + 1));
}
QCOMPARE(wake_Thread::count, 0);
QCOMPARE(count.load(), 0);
// QReadWriteLock
QReadWriteLock readWriteLock;
wake_Thread_2 rwthread[ThreadCount];
prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_readwritelock_")
+ QString::number(i) + QLatin1Char('_');
readWriteLock.lockForWrite();
for (x = 0; x < ThreadCount; ++x) {
rwthread[x].setObjectName(prefix + QString::number(x));
rwthread[x].count = &count;
rwthread[x].readWriteLock = &readWriteLock;
rwthread[x].cond = &cond;
thread_exited[x] = false;
@ -482,7 +535,7 @@ void tst_QWaitCondition::wakeOne()
}
readWriteLock.unlock();
QCOMPARE(wake_Thread_2::count, ThreadCount);
QCOMPARE(count.load(), ThreadCount);
// wake up threads one at a time
for (x = 0; x < ThreadCount; ++x) {
@ -496,17 +549,17 @@ void tst_QWaitCondition::wakeOne()
for (int y = 0; y < ThreadCount; ++y) {
if (thread_exited[y])
continue;
if (rwthread[y].wait(exited > 0 ? 10 : 1000)) {
if (rwthread[y].wait(exited > 0 ? waitInterval : firstWaitInterval)) {
thread_exited[y] = true;
++exited;
}
}
QCOMPARE(exited, 1);
QCOMPARE(wake_Thread_2::count, ThreadCount - (x + 1));
QCOMPARE(count.load(), ThreadCount - (x + 1));
}
QCOMPARE(wake_Thread_2::count, 0);
QCOMPARE(count.load(), 0);
}
// wake up threads, two at a time
@ -518,8 +571,13 @@ void tst_QWaitCondition::wakeOne()
wake_Thread thread[ThreadCount];
bool thread_exited[ThreadCount];
QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_mutex2_")
+ QString::number(i) + QLatin1Char('_');
mutex.lock();
for (x = 0; x < ThreadCount; ++x) {
thread[x].setObjectName(prefix + QString::number(x));
thread[x].count = &count;
thread[x].mutex = &mutex;
thread[x].cond = &cond;
thread_exited[x] = false;
@ -532,7 +590,7 @@ void tst_QWaitCondition::wakeOne()
}
mutex.unlock();
QCOMPARE(wake_Thread::count, ThreadCount);
QCOMPARE(count.load(), ThreadCount);
// wake up threads one at a time
for (x = 0; x < ThreadCount; x += 2) {
@ -548,24 +606,29 @@ void tst_QWaitCondition::wakeOne()
for (int y = 0; y < ThreadCount; ++y) {
if (thread_exited[y])
continue;
if (thread[y].wait(exited > 0 ? 10 : 1000)) {
if (thread[y].wait(exited > 0 ? waitInterval : firstWaitInterval)) {
thread_exited[y] = true;
++exited;
}
}
QCOMPARE(exited, 2);
QCOMPARE(wake_Thread::count, ThreadCount - (x + 2));
QCOMPARE(count.load(), ThreadCount - (x + 2));
}
QCOMPARE(wake_Thread::count, 0);
QCOMPARE(count.load(), 0);
// QReadWriteLock
QReadWriteLock readWriteLock;
wake_Thread_2 rwthread[ThreadCount];
prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_readwritelock_")
+ QString::number(i) + QLatin1Char('_');
readWriteLock.lockForWrite();
for (x = 0; x < ThreadCount; ++x) {
rwthread[x].setObjectName(prefix + QString::number(x));
rwthread[x].count = &count;
rwthread[x].readWriteLock = &readWriteLock;
rwthread[x].cond = &cond;
thread_exited[x] = false;
@ -578,7 +641,7 @@ void tst_QWaitCondition::wakeOne()
}
readWriteLock.unlock();
QCOMPARE(wake_Thread_2::count, ThreadCount);
QCOMPARE(count.load(), ThreadCount);
// wake up threads one at a time
for (x = 0; x < ThreadCount; x += 2) {
@ -594,23 +657,24 @@ void tst_QWaitCondition::wakeOne()
for (int y = 0; y < ThreadCount; ++y) {
if (thread_exited[y])
continue;
if (rwthread[y].wait(exited > 0 ? 10 : 1000)) {
if (rwthread[y].wait(exited > 0 ? waitInterval : firstWaitInterval)) {
thread_exited[y] = true;
++exited;
}
}
QCOMPARE(exited, 2);
QCOMPARE(wake_Thread_2::count, ThreadCount - (x + 2));
QCOMPARE(count.load(), ThreadCount - (x + 2));
}
QCOMPARE(wake_Thread_2::count, 0);
QCOMPARE(count.load(), 0);
}
}
void tst_QWaitCondition::wakeAll()
{
int x;
QAtomicInt count;
for (int i = 0; i < iterations; ++i) {
QMutex mutex;
QWaitCondition cond;
@ -618,8 +682,13 @@ void tst_QWaitCondition::wakeAll()
// QMutex
wake_Thread thread[ThreadCount];
QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_mutex_")
+ QString::number(i) + QLatin1Char('_');
mutex.lock();
for (x = 0; x < ThreadCount; ++x) {
thread[x].setObjectName(prefix + QString::number(x));
thread[x].count = &count;
thread[x].mutex = &mutex;
thread[x].cond = &cond;
thread[x].start();
@ -628,7 +697,7 @@ void tst_QWaitCondition::wakeAll()
}
mutex.unlock();
QCOMPARE(wake_Thread::count, ThreadCount);
QCOMPARE(count.load(), ThreadCount);
// wake up all threads at once
mutex.lock();
@ -643,14 +712,19 @@ void tst_QWaitCondition::wakeAll()
}
QCOMPARE(exited, ThreadCount);
QCOMPARE(wake_Thread::count, 0);
QCOMPARE(count.load(), 0);
// QReadWriteLock
QReadWriteLock readWriteLock;
wake_Thread_2 rwthread[ThreadCount];
prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_readwritelock_")
+ QString::number(i) + QLatin1Char('_');
readWriteLock.lockForWrite();
for (x = 0; x < ThreadCount; ++x) {
rwthread[x].setObjectName(prefix + QString::number(x));
rwthread[x].count = &count;
rwthread[x].readWriteLock = &readWriteLock;
rwthread[x].cond = &cond;
rwthread[x].start();
@ -659,7 +733,7 @@ void tst_QWaitCondition::wakeAll()
}
readWriteLock.unlock();
QCOMPARE(wake_Thread_2::count, ThreadCount);
QCOMPARE(count.load(), ThreadCount);
// wake up all threads at once
readWriteLock.lockForWrite();
@ -674,11 +748,11 @@ void tst_QWaitCondition::wakeAll()
}
QCOMPARE(exited, ThreadCount);
QCOMPARE(wake_Thread_2::count, 0);
QCOMPARE(count.load(), 0);
}
}
class wait_RaceConditionThread : public QThread
class wait_RaceConditionThread : public TerminatingThread
{
public:
wait_RaceConditionThread(QMutex *mutex, QWaitCondition *startup, QWaitCondition *waitCondition,
@ -707,7 +781,7 @@ public:
}
};
class wait_RaceConditionThread_2 : public QThread
class wait_RaceConditionThread_2 : public TerminatingThread
{
public:
wait_RaceConditionThread_2(QReadWriteLock *readWriteLock,

View File

@ -36,7 +36,6 @@
#include <QBuffer>
#include <QDebug>
#include <QFile>
#include <QImage>
#include <QImageReader>
#include <QImageWriter>
@ -46,6 +45,7 @@
#include <QTcpServer>
#include <QTimer>
#include <QTemporaryDir>
#include <QTemporaryFile>
#include <algorithm>
@ -53,6 +53,22 @@ typedef QMap<QString, QString> QStringMap;
typedef QList<int> QIntList;
Q_DECLARE_METATYPE(QImage::Format)
static QByteArray msgFileOpenWriteFailed(const QFile &file)
{
const QString result = QLatin1String("Cannot open \"")
+ QDir::toNativeSeparators(file.fileName())
+ QLatin1String("\" for writing: ") + file.errorString();
return result.toLocal8Bit();
}
static QByteArray msgFileOpenReadFailed(const QFile &file)
{
const QString result = QLatin1String("Cannot open \"")
+ QDir::toNativeSeparators(file.fileName())
+ QLatin1String("\" for reading: ") + file.errorString();
return result.toLocal8Bit();
}
class tst_QImageReader : public QObject
{
Q_OBJECT
@ -1051,7 +1067,7 @@ void tst_QImageReader::readFromDevice()
const QString imageFileName = prefix + fileName;
QImage expectedImage(imageFileName, format);
QFile file(imageFileName);
QVERIFY(file.open(QFile::ReadOnly));
QVERIFY2(file.open(QFile::ReadOnly), msgFileOpenReadFailed(file).constData());
QByteArray imageData = file.readAll();
QVERIFY(!imageData.isEmpty());
{
@ -1129,12 +1145,11 @@ void tst_QImageReader::readFromFileAfterJunk()
SKIP_IF_UNSUPPORTED(format);
QFile::remove("junk");
QFile junkFile("junk");
QVERIFY(junkFile.open(QFile::WriteOnly));
QTemporaryFile junkFile(m_temporaryDir.path() + QLatin1String("/junkXXXXXX"));
QVERIFY2(junkFile.open(), msgFileOpenWriteFailed(junkFile).constData());
QFile imageFile(prefix + fileName);
QVERIFY(imageFile.open(QFile::ReadOnly));
QVERIFY2(imageFile.open(QFile::ReadOnly), msgFileOpenReadFailed(imageFile).constData());
QByteArray imageData = imageFile.readAll();
QVERIFY(!imageData.isNull());
@ -1155,7 +1170,7 @@ void tst_QImageReader::readFromFileAfterJunk()
}
}
junkFile.close();
junkFile.open(QFile::ReadOnly);
QVERIFY2(junkFile.open(), msgFileOpenReadFailed(junkFile).constData());
for (int i = 0; i < iterations; ++i) {
QByteArray ole = junkFile.read(9);
@ -1205,7 +1220,7 @@ void tst_QImageReader::devicePosition()
QVERIFY(!expected.isNull());
QFile imageFile(prefix + fileName);
QVERIFY(imageFile.open(QFile::ReadOnly));
QVERIFY2(imageFile.open(QFile::ReadOnly), msgFileOpenReadFailed(imageFile).constData());
QByteArray imageData = imageFile.readAll();
QVERIFY(!imageData.isNull());
int imageDataSize = imageData.size();

View File

@ -89,6 +89,7 @@ private slots:
void saveToTemporaryFile();
private:
QTemporaryDir m_temporaryDir;
QString prefix;
QString writePrefix;
};
@ -112,14 +113,11 @@ static void initializePadding(QImage *image)
void tst_QImageWriter::initTestCase()
{
QVERIFY(m_temporaryDir.isValid());
prefix = QFINDTESTDATA("images/");
if (prefix.isEmpty())
QFAIL("Can't find images directory!");
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK)
writePrefix = QDir::homePath();
#else
writePrefix = prefix;
#endif
writePrefix = m_temporaryDir.path();
}
// Testing get/set functions

View File

@ -202,8 +202,7 @@ protected Q_SLOTS:
void notEnoughData();
private Q_SLOTS:
void init();
void cleanup();
void cleanup() { cleanupTestData(); }
void initTestCase();
void cleanupTestCase();
@ -487,6 +486,8 @@ private Q_SLOTS:
// NOTE: This test must be last!
void parentingRepliesToTheApp();
private:
void cleanupTestData();
QString testDataDir;
bool notEnoughDataForFastSender;
};
@ -1499,6 +1500,8 @@ void tst_QNetworkReply::initTestCase()
echoProcessDir = QFINDTESTDATA("echo");
QVERIFY2(!echoProcessDir.isEmpty(), qPrintable(
QString::fromLatin1("Couldn't find echo dir starting from %1.").arg(QDir::currentPath())));
cleanupTestData();
}
void tst_QNetworkReply::cleanupTestCase()
@ -1514,12 +1517,7 @@ void tst_QNetworkReply::cleanupTestCase()
#endif
}
void tst_QNetworkReply::init()
{
cleanup();
}
void tst_QNetworkReply::cleanup()
void tst_QNetworkReply::cleanupTestData()
{
QFile file(testFileName);
QVERIFY(!file.exists() || file.remove());

View File

@ -0,0 +1,5 @@
# Created by various tests, even for shadow builds:
/pro_file_cache/include.pri
/quotedfilenames/cpp folder/
/quotedfilenames/quotedfilenames
/resources/resources

View File

@ -1,3 +1,3 @@
TEMPLATE = subdirs
SUBDIRS = allcursors grab_override
SUBDIRS = allcursors grab_override qcursorhighdpi

View File

@ -0,0 +1,321 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite 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$
**
****************************************************************************/
#include <QAction>
#include <QApplication>
#include <QDesktopWidget>
#include <QGridLayout>
#include <QLabel>
#include <QMainWindow>
#include <QMenu>
#include <QMenuBar>
#include <QSharedPointer>
#include <QToolBar>
#include <QBitmap>
#include <QCursor>
#include <QPainter>
#include <QPixmap>
#include <QDebug>
#include <QStringList>
#include <QTextStream>
#if QT_VERSION > 0x050000
# include <QScreen>
# include <QWindow>
# include <private/qhighdpiscaling_p.h>
# include <qpa/qplatformwindow.h>
#else
# define Q_NULLPTR 0
# define Q_DECL_OVERRIDE
#endif
#ifdef Q_OS_WIN
# include <qt_windows.h>
#endif
#include <algorithm>
#include <iterator>
// High DPI cursor test for testing cursor sizes in multi-screen setups.
// It creates one widget per screen with a grid of standard cursors,
// pixmap / bitmap cursors and pixmap / bitmap cursors with device pixel ratio 2.
// On the left, there is a ruler with 10 DIP marks.
// The code is meant to compile with Qt 4 also.
static QString screenInfo(const QWidget *w)
{
QString result;
QTextStream str(&result);
#if QT_VERSION > 0x050000
QScreen *screen = Q_NULLPTR;
if (const QWindow *window = w->windowHandle())
screen = window->screen();
if (screen) {
str << '"' << screen->name() << "\" " << screen->size().width() << 'x'
<< screen->size().height() << ", DPR=" << screen->devicePixelRatio()
<< ", " << screen->logicalDotsPerInchX() << "DPI ";
if (QHighDpiScaling::isActive())
str << ", factor=" << QHighDpiScaling::factor(screen);
else
str << ", no scaling";
} else {
str << "<null>";
}
#else
QDesktopWidget *desktop = QApplication::desktop();
int screenNumber = desktop->screenNumber(w);
str << "Screen #" <<screenNumber << ' ' << desktop->screenGeometry(screenNumber).width()
<< 'x' << desktop->screenGeometry(screenNumber).height() << " PD: " << w->logicalDpiX() << "DPI";
#endif
#ifdef Q_OS_WIN
str << ", SM_C_CURSOR: " << GetSystemMetrics(SM_CXCURSOR) << 'x' << GetSystemMetrics(SM_CYCURSOR);
#endif
return result;
}
// Helpers for painting pixmaps and creating cursors
static QPixmap paintPixmap(int size, QColor c)
{
QPixmap result(size, size);
result.fill(c);
QPainter p(&result);
p.drawRect(QRect(QPoint(0, 0), result.size() - QSize(1, 1)));
p.drawLine(0, 0, size, size);
p.drawLine(0, size, size, 0);
return result;
}
static QCursor pixmapCursor(int size)
{
QCursor result(paintPixmap(size, Qt::red), size / 2, size / 2);
return result;
}
static QPair<QBitmap, QBitmap> paintBitmaps(int size)
{
QBitmap bitmap(size, size);
bitmap.fill(Qt::color1);
QBitmap mask(size, size);
mask.fill(Qt::color1);
{
QPainter mp(&mask);
mp.fillRect(QRect(0, 0, size / 2, size / 2), Qt::color0);
}
return QPair<QBitmap, QBitmap>(bitmap, mask);
}
static QCursor bitmapCursor(int size)
{
QPair<QBitmap, QBitmap> bitmaps = paintBitmaps(size);
return QCursor(bitmaps.first, bitmaps.second, size / 2, size / 2);
}
#if QT_VERSION > 0x050000
static QCursor pixmapCursorDevicePixelRatio(int size, int dpr)
{
QPixmap pixmap = paintPixmap(dpr * size, Qt::yellow);
pixmap.setDevicePixelRatio(dpr);
return QCursor(pixmap, size / 2, size / 2);
}
static QCursor bitmapCursorDevicePixelRatio(int size, int dpr)
{
QPair<QBitmap, QBitmap> bitmaps = paintBitmaps(dpr * size);
bitmaps.first.setDevicePixelRatio(dpr);
bitmaps.second.setDevicePixelRatio(dpr);
return QCursor(bitmaps.first, bitmaps.second, size / 2, size / 2);
}
#endif // Qt 5
// Vertical ruler widget with 10 px marks
class VerticalRuler : public QWidget {
public:
VerticalRuler(QWidget *parent = Q_NULLPTR);
protected:
void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;
};
VerticalRuler::VerticalRuler(QWidget *parent) : QWidget(parent)
{
const int screenWidth = QApplication::desktop()->screenGeometry(this).width();
setFixedWidth(screenWidth / 48); // 1920 pixel monitor ->40
}
void VerticalRuler::paintEvent(QPaintEvent *)
{
const QSize sizeS(size());
const QPoint sizeP(sizeS.width(), sizeS.height());
const QPoint center = sizeP / 2;
QPainter painter(this);
painter.fillRect(QRect(QPoint(0, 0), sizeS), Qt::white);
painter.drawLine(center.x(), 0, center.x(), sizeP.y());
for (int y = 0; y < sizeP.y(); y += 10)
painter.drawLine(center.x() - 5, y, center.x() + 5, y);
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = Q_NULLPTR);
void updateScreenInfo() { m_screenInfoLabel->setText(screenInfo(this)); }
public slots:
void screenChanged() { updateScreenInfo(); }
private:
QLabel *m_screenInfoLabel;
};
static QLabel *createCursorLabel(const QCursor &cursor, const QString &additionalText = QString())
{
QString labelText;
QDebug(&labelText).nospace() << cursor.shape();
#if QT_VERSION > 0x050000
labelText.remove(0, labelText.indexOf('(') + 1);
labelText.chop(1);
#endif // Qt 5
if (!additionalText.isEmpty())
labelText += ' ' + additionalText;
QLabel *result = new QLabel(labelText);
result->setFrameShape(QFrame::Box);
result->setCursor(cursor);
return result;
}
static void addToGrid(QWidget *w, QGridLayout *gridLayout, int columnCount, int &row, int &col)
{
gridLayout->addWidget(w, row, col);
if (col >= columnCount) {
col = 0;
row++;
} else {
col++;
}
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, m_screenInfoLabel(new QLabel)
{
QString title = "Cursors ";
#if QT_VERSION > 0x050000
title += '(' + QGuiApplication::platformName() + ") ";
#endif
title += QT_VERSION_STR;
setWindowTitle(title);
QMenu *fileMenu = menuBar()->addMenu("File");
QAction *quitAction = fileMenu->addAction("Quit");
quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
QToolBar *fileToolBar = addToolBar("File");
fileToolBar->addAction(quitAction);
QWidget *cw = new QWidget;
QHBoxLayout *hLayout = new QHBoxLayout(cw);
hLayout->addWidget(new VerticalRuler(cw));
QGridLayout *gridLayout = new QGridLayout;
hLayout->addLayout(gridLayout);
const int columnCount = 5;
const int size = 32;
int row = 0;
int col = 0;
for (int i = 0; i < Qt::BitmapCursor; ++i)
addToGrid(createCursorLabel(QCursor(static_cast<Qt::CursorShape>(i))), gridLayout, columnCount, row, col);
addToGrid(createCursorLabel(QCursor(pixmapCursor(size)),
QLatin1String("Plain PX ") + QString::number(size)),
gridLayout, columnCount, row, col);
addToGrid(createCursorLabel(bitmapCursor(size),
QLatin1String("Plain BM ") + QString::number(size)),
gridLayout, columnCount, row, col);
#if QT_VERSION > 0x050000
addToGrid(createCursorLabel(QCursor(pixmapCursorDevicePixelRatio(size, 2)),
"PX with DPR 2 " + QString::number(size)),
gridLayout, columnCount, row, col);
addToGrid(createCursorLabel(QCursor(bitmapCursorDevicePixelRatio(size, 2)),
"BM with DPR 2 " + QString::number(size)),
gridLayout, columnCount, row, col);
#endif // Qt 5
gridLayout->addWidget(m_screenInfoLabel, row + 1, 0, 1, columnCount);
setCentralWidget(cw);
}
typedef QSharedPointer<MainWindow> MainWindowPtr;
typedef QList<MainWindowPtr> MainWindowPtrList;
int main(int argc, char *argv[])
{
QStringList arguments;
std::copy(argv + 1, argv + argc, std::back_inserter(arguments));
#if QT_VERSION > 0x050000
if (arguments.contains("-s"))
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
else if (arguments.contains("-n"))
QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
#endif // Qt 5
QApplication app(argc, argv);
MainWindowPtrList windows;
QDesktopWidget *desktopWidget = app.desktop();
for (int s = desktopWidget->screenCount() - 1; s >= 0; --s) {
MainWindowPtr window(new MainWindow(desktopWidget->screen(s)));
const QPoint pos = desktopWidget->screenGeometry(s).center() - QPoint(200, 100);
window->move(pos);
windows.append(window);
window->show();
window->updateScreenInfo();
#if QT_VERSION > 0x050000
QObject::connect(window->windowHandle(), &QWindow::screenChanged,
window.data(), &MainWindow::updateScreenInfo);
#endif
}
return app.exec();
}
#include "main.moc"

View File

@ -0,0 +1,6 @@
TEMPLATE = app
QT = core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += gui-private core-private widgets
CONFIG -= app_bundle
SOURCES += main.cpp
win32: LIBS += -lUser32