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 #endif
// -- ARM -- // -- ARM --
#ifdef __ARM_NEON__ #if defined(__ARM_NEON) || defined(__ARM_NEON__)
" neon" " neon"
#endif #endif
#ifdef __IWMMXT__ #ifdef __IWMMXT__

4
configure vendored
View File

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

View File

@ -105,6 +105,10 @@
\externalpage http://doc.qt.io/qtcreator/qtcreator-transitions-example.html \externalpage http://doc.qt.io/qtcreator/qtcreator-transitions-example.html
\title Qt Creator: Creating a Qt Quick Application \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 \externalpage http://doc.qt.io/qtcreator/quick-export-to-qml.html
\title Qt Creator: Exporting Designs from Graphics Software \title Qt Creator: Exporting Designs from Graphics Software
@ -209,6 +213,10 @@
\externalpage http://doc.qt.io/qtcreator/creator-mime-types.html \externalpage http://doc.qt.io/qtcreator/creator-mime-types.html
\title Qt Creator: Editing MIME Types \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 \externalpage http://doc.qt.io/qtcreator/creator-qml-debugging-example.html
\title Qt Creator: Debugging a Qt Quick Example Application \title Qt Creator: Debugging a Qt Quick Example Application

View File

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

View File

@ -19,6 +19,8 @@ if(win32|mac):!macx-xcode {
contains(QT_CONFIG, build_all):CONFIG += build_all 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) { !no_cxx_module:isEmpty(CXX_MODULE) {
CXX_MODULE = $$TARGET CXX_MODULE = $$TARGET
TARGET = declarative_$${TARGET} TARGET = declarative_$${TARGET}

View File

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

View File

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

View File

@ -596,14 +596,11 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
continue; continue;
} }
x++; 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; 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] == '"') { } else if (buffer[x] == '\'' || buffer[x] == '"') {
const char term = buffer[x++]; const char term = buffer[x++];
while(x < buffer_len) { while(x < buffer_len) {

View File

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

View File

@ -590,7 +590,7 @@ void QCoreApplicationPrivate::initLocale()
\section1 The Event Loop and Event Handling \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 operations can call processEvents() to keep the application
responsive. responsive.
@ -672,7 +672,7 @@ QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p)
#ifndef QT_NO_QOBJECT #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 If you are doing graphical changes inside a loop that does not
return to the event loop on asynchronous window systems like X11 return to the event loop on asynchronous window systems like X11
@ -690,9 +690,9 @@ void QCoreApplication::flush()
#endif #endif
/*! /*!
Constructs a Qt kernel application. Kernel applications are Constructs a Qt core application. Core applications are applications without
applications without a graphical user interface. These type of a graphical user interface. Such applications are used at the console or as
applications are used at the console or as server processes. server processes.
The \a argc and \a argv arguments are processed by the application, The \a argc and \a argv arguments are processed by the application,
and made available in a more convenient form by the arguments() 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, milliseconds or until there are no more events to process,
whichever is shorter. 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). doing a long operation (e.g. copying a file).
Calling this function processes events only for the calling thread. 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. Enters the main event loop and waits until exit() is called. Returns
Returns the value that was set to exit() (which is 0 if exit() is the value that was passed to exit() (which is 0 if exit() is called via
called via quit()). quit()).
It is necessary to call this function to start event handling. The It is necessary to call this function to start event handling. The
main event loop receives events from the window system and 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 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. 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() \sa flush(), postEvent()
*/ */
@ -1805,7 +1806,7 @@ void QCoreApplication::quit()
This signal is emitted when the application is about to quit the 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. 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 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 The signal is particularly useful if your application has to do some
last-second cleanup. Note that no user interaction is possible in 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 directory, and you run the \c{regexp} example, this function will
return "C:/Qt/examples/tools/regexp". return "C:/Qt/examples/tools/regexp".
On OS X and iOS this will point to the directory actually containing the On OS X and iOS this will point to the directory actually containing
executable, which may be inside of an application bundle (if the the executable, which may be inside an application bundle (if the
application is bundled). application is bundled).
\warning On Linux, this function will try to get the path from the \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()} 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. function, which is called for all native events received in the main thread.
The QAbstractNativeEventFilter::nativeEventFilter() function should return true if the event should The QAbstractNativeEventFilter::nativeEventFilter() function should
be filtered, (i.e. stopped). It should return false to allow return true if the event should be filtered, i.e. stopped. It should
normal Qt processing to continue: the native event can then be translated return false to allow normal Qt processing to continue: the native
into a QEvent and handled by the standard Qt \l{QEvent} {event} filtering, event can then be translated into a QEvent and handled by the standard
e.g. QObject::installEventFilter(). Qt \l{QEvent} {event} filtering, e.g. QObject::installEventFilter().
If multiple event filters are installed, the filter that was If multiple event filters are installed, the filter that was
installed last is activated first. installed last is activated first.
@ -2616,7 +2617,7 @@ void QCoreApplication::removeLibraryPath(const QString &path)
\note The filter function set here receives native messages, \note The filter function set here receives native messages,
i.e. MSG or XCB event structs. 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. Qt::AA_PluginApplication attribute is set.
For maximum portability, you should always try to use QEvent 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 \snippet code/src_corelib_kernel_qcoreapplication.cpp 7
The \a context parameter is normally the class name, but it can 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() \sa Q_OBJECT, QObject::tr(), QObject::trUtf8()
*/ */

View File

@ -251,9 +251,13 @@
// NEON intrinsics // NEON intrinsics
// note: as of GCC 4.9, does not support function targets for ARM // 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> #include <arm_neon.h>
#define QT_FUNCTION_TARGET_STRING_ARM_NEON "neon" #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 #endif
#undef QT_COMPILER_SUPPORTS_SIMD_ALWAYS #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); 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) 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__ #ifdef __SSE2__
convert_ARGB_to_ARGB_PM_inplace_sse2, convert_ARGB_to_ARGB_PM_inplace_sse2,
#else #else
0, convert_ARGB_to_ARGB_PM_inplace,
#endif #endif
0, 0,
0, 0,
@ -2705,12 +2730,13 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0, 0,
0, 0,
mask_alpha_converter_rgbx_inplace, mask_alpha_converter_rgbx_inplace,
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN && __SSE2__
0, 0,
#ifdef __SSE2__
convert_ARGB_to_ARGB_PM_inplace_sse2, convert_ARGB_to_ARGB_PM_inplace_sse2,
#elif Q_BYTE_ORDER == Q_LITTLE_ENDIAN
convert_ARGB_to_ARGB_PM_inplace,
#else #else
0, 0,
0,
#endif #endif
0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0
}, // Format_RGBA8888 }, // Format_RGBA8888
@ -2921,7 +2947,7 @@ void qInitImageConversions()
} }
#endif #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); 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_RGB32] = convert_RGB888_to_RGB32_neon;
qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = 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/qimage_p.h>
#include <private/qsimd_p.h> #include <private/qsimd_p.h>
#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) #if defined(__ARM_NEON__)
QT_BEGIN_NAMESPACE 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) { if ((len - offsetToAlignOn8Bytes) >= 8) {
const quint32 *const simdEnd = end - 7; const quint32 *const simdEnd = end - 7;
#if !defined(Q_PROCESSOR_ARM_64)
register uint8x8_t fullVector asm ("d3") = vdup_n_u8(0xff); register uint8x8_t fullVector asm ("d3") = vdup_n_u8(0xff);
do { do {
#if Q_BYTE_ORDER == Q_BIG_ENDIAN #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 #endif
} while (dst < simdEnd); } 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) { while (dst != end) {
@ -103,4 +129,4 @@ void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::I
QT_END_NAMESPACE 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() QJpegHandler::QJpegHandler()
: d(new QJpegHandlerPrivate(this)) : d(new QJpegHandlerPrivate(this))
{ {
#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) #if defined(__ARM_NEON__)
// from qimage_neon.cpp // from qimage_neon.cpp
if (qCpuHasFeature(NEON)) if (qCpuHasFeature(NEON))
d->rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_neon; d->rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_neon;
#endif #endif

View File

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

View File

@ -3418,6 +3418,21 @@ QShowEvent::~QShowEvent()
It may be safely ignored. It may be safely ignored.
\note This class is currently supported for OS X only. \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 painting/qimagescale_sse4.cpp
AVX2_SOURCES += painting/qdrawhelper_avx2.cpp AVX2_SOURCES += painting/qdrawhelper_avx2.cpp
!ios { !ios:!contains(QT_ARCH, "arm64") {
CONFIG += no_clang_integrated_as CONFIG += no_clang_integrated_as
NEON_SOURCES += painting/qdrawhelper_neon.cpp NEON_SOURCES += painting/qdrawhelper_neon.cpp
NEON_HEADERS += painting/qdrawhelper_neon_p.h 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); qt_memfill_template<quint16>(dest, color, count);
} }
#endif #endif
#if !defined(__SSE2__) && !defined(__ARM_NEON__) #if !defined(__SSE2__) && (!defined(__ARM_NEON__) || defined(Q_PROCESSOR_ARM_64))
# ifdef QT_COMPILER_SUPPORTS_MIPS_DSP # ifdef QT_COMPILER_SUPPORTS_MIPS_DSP
extern "C" void qt_memfill32_asm_mips_dsp(quint32 *, quint32, int); extern "C" void qt_memfill32_asm_mips_dsp(quint32 *, quint32, int);
# endif # endif
@ -6425,7 +6425,7 @@ void qInitDrawhelperAsm()
#endif // SSE2 #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_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_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; 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/qblendfunctions_p.h>
#include <private/qmath_p.h> #include <private/qmath_p.h>
#ifdef __ARM_NEON__ #ifdef __ARM_NEON__
#include <private/qdrawhelper_neon_p.h>
#include <private/qpaintengine_raster_p.h> #include <private/qpaintengine_raster_p.h>
#include <arm_neon.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE

View File

@ -58,10 +58,10 @@ inline Q_DECL_CONSTEXPR int qAlpha(QRgb rgb) // get alpha part of
{ return rgb >> 24; } { return rgb >> 24; }
inline Q_DECL_CONSTEXPR QRgb qRgb(int r, int g, int b)// set RGB value 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 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 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; } { return (r*11+g*16+b*5)/32; }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -89,10 +89,11 @@ QIOSIntegration::QIOSIntegration()
// Set current directory to app bundle folder // Set current directory to app bundle folder
QDir::setCurrent(QString::fromUtf8([[[NSBundle mainBundle] bundlePath] UTF8String])); QDir::setCurrent(QString::fromUtf8([[[NSBundle mainBundle] bundlePath] UTF8String]));
UIScreen *mainScreen = [UIScreen mainScreen];
NSMutableArray *screens = [[[UIScreen screens] mutableCopy] autorelease]; NSMutableArray *screens = [[[UIScreen screens] mutableCopy] autorelease];
if (![screens containsObject:[UIScreen mainScreen]]) { if (![screens containsObject:mainScreen]) {
// Fallback for iOS 7.1 (QTBUG-42345) // Fallback for iOS 7.1 (QTBUG-42345)
[screens insertObject:[UIScreen mainScreen] atIndex:0]; [screens insertObject:mainScreen atIndex:0];
} }
for (UIScreen *screen in screens) for (UIScreen *screen in screens)
@ -103,7 +104,10 @@ QIOSIntegration::QIOSIntegration()
m_touchDevice = new QTouchDevice; m_touchDevice = new QTouchDevice;
m_touchDevice->setType(QTouchDevice::TouchScreen); 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); QWindowSystemInterface::registerTouchDevice(m_touchDevice);
QMacInternalPasteboardMime::initializeMimeTypes(); 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 -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{ {
if (m_qioswindow->window()->flags() & Qt::WindowTransparentForInput) if (m_qioswindow->window()->flags() & Qt::WindowTransparentForInput)
@ -289,6 +302,8 @@
- (void)updateTouchList:(NSSet *)touches withState:(Qt::TouchPointState)state - (void)updateTouchList:(NSSet *)touches withState:(Qt::TouchPointState)state
{ {
bool supportsPressure = QIOSIntegration::instance()->touchDevice()->capabilities() & QTouchDevice::Pressure;
foreach (UITouch *uiTouch, m_activeTouches.keys()) { foreach (UITouch *uiTouch, m_activeTouches.keys()) {
QWindowSystemInterface::TouchPoint &touchPoint = m_activeTouches[uiTouch]; QWindowSystemInterface::TouchPoint &touchPoint = m_activeTouches[uiTouch];
if (![touches containsObject:uiTouch]) { if (![touches containsObject:uiTouch]) {
@ -309,9 +324,17 @@
touchPoint.normalPosition = QPointF(globalScreenPosition.x() / screenSize.width(), touchPoint.normalPosition = QPointF(globalScreenPosition.x() / screenSize.width(),
globalScreenPosition.y() / screenSize.height()); globalScreenPosition.y() / screenSize.height());
// We don't claim that our touch device supports QTouchDevice::Pressure, if (supportsPressure) {
// but fill in a meaningfull value in case clients use it anyways. // Note: iOS will deliver touchesBegan with a touch force of 0, which
touchPoint.pressure = (state == Qt::TouchPointReleased) ? 0.0 : 1.0; // 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 &) const QStringList &)
{ {
if (system.toLower() == "mirclient") { 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; return new QMirClientClientIntegration;
} else { } else {
return 0; return 0;

View File

@ -43,15 +43,17 @@
#include <QtGui/QGuiApplication> #include <QtGui/QGuiApplication>
#include <QtGui/QScreen> #include <QtGui/QScreen>
#include <QtGui/private/qguiapplication_p.h> // getPixmapCursor() #include <QtGui/private/qguiapplication_p.h> // getPixmapCursor()
#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <QtCore/QScopedArrayPointer> #include <QtCore/QScopedArrayPointer>
static void initResources() static bool initResources()
{ {
#if !defined (Q_OS_WINCE) && !defined (QT_NO_IMAGEFORMAT_PNG) #if !defined (Q_OS_WINCE) && !defined (QT_NO_IMAGEFORMAT_PNG)
Q_INIT_RESOURCE(cursors); Q_INIT_RESOURCE(cursors);
#endif #endif
return true;
} }
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -92,9 +94,14 @@ QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c)
\sa QWindowsWindowCursor \sa QWindowsWindowCursor
*/ */
HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot) HCURSOR QWindowsCursor::createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor)
{ {
HCURSOR cur = 0; 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(); QBitmap mask = pixmap.mask();
if (mask.isNull()) { if (mask.isNull()) {
mask = QBitmap(pixmap.size()); 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. // 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()); Q_ASSERT(cursor.shape() == Qt::BitmapCursor && cursor.bitmap());
const QImage bbits = cursor.bitmap()->toImage().convertToFormat(QImage::Format_Mono); QImage bbits = cursor.bitmap()->toImage();
const QImage mbits = cursor.mask()->toImage().convertToFormat(QImage::Format_Mono); 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 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)); const bool invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1));
return createBitmapCursor(bbits, mbits, cursor.hotSpot(), invb, invm); 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); } static inline QSize standardCursorSize() { return QSize(32, 32); }
#if defined (Q_OS_WINCE) || defined (QT_NO_IMAGEFORMAT_PNG) #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); 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 // Non-standard Windows cursors are created from bitmaps
static const uchar vsplit_bits[] = { static const uchar vsplit_bits[] = {
@ -410,13 +444,13 @@ QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursor
switch (cursorShape) { switch (cursorShape) {
case Qt::SplitVCursor: 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: 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: 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: 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: case Qt::DragCopyCursor:
return QWindowsCursor::PixmapCursor(QPixmap(copyDragCursorXpmC), QPoint(0, 0)); return QWindowsCursor::PixmapCursor(QPixmap(copyDragCursorXpmC), QPoint(0, 0));
case Qt::DragMoveCursor: case Qt::DragMoveCursor:
@ -436,7 +470,7 @@ struct QWindowsCustomPngCursor {
int hotSpotY; int hotSpotY;
}; };
QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape) QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape, const QPlatformScreen *screen)
{ {
static const QWindowsCustomPngCursor pngCursors[] = { static const QWindowsCustomPngCursor pngCursors[] = {
{ Qt::SplitVCursor, 32, "splitvcursor_32.png", 11, 11 }, { 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 } { 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 *sEnd = pngCursors + sizeof(pngCursors) / sizeof(pngCursors[0]);
const QWindowsCustomPngCursor *bestFit = 0; const QWindowsCustomPngCursor *bestFit = 0;
int sizeDelta = INT_MAX; int sizeDelta = INT_MAX;
for (const QWindowsCustomPngCursor *s = pngCursors; s < sEnd; ++s) { for (const QWindowsCustomPngCursor *s = pngCursors; s < sEnd; ++s) {
if (s->shape != cursorShape) if (s->shape != cursorShape)
continue; 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) { if (currentSizeDelta < sizeDelta) {
bestFit = s; bestFit = s;
if (currentSizeDelta == 0) if (currentSizeDelta == 0)
@ -492,7 +526,7 @@ struct QWindowsStandardCursorMapping {
LPCWSTR resource; LPCWSTR resource;
}; };
HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape) HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape, const QPlatformScreen *screen)
{ {
Q_ASSERT(cursorShape != Qt::BitmapCursor); Q_ASSERT(cursorShape != Qt::BitmapCursor);
@ -515,7 +549,7 @@ HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape)
switch (cursorShape) { switch (cursorShape) {
case Qt::BlankCursor: { case Qt::BlankCursor: {
QImage blank = QImage(systemCursorSize(), QImage::Format_Mono); QImage blank = QImage(systemCursorSize(screen), QImage::Format_Mono);
blank.fill(0); // ignore color table blank.fill(0); // ignore color table
return createBitmapCursor(blank, blank); return createBitmapCursor(blank, blank);
} }
@ -526,7 +560,7 @@ HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape)
case Qt::DragCopyCursor: case Qt::DragCopyCursor:
case Qt::DragMoveCursor: case Qt::DragMoveCursor:
case Qt::DragLinkCursor: case Qt::DragLinkCursor:
return QWindowsCursor::createPixmapCursor(customCursor(cursorShape)); return QWindowsCursor::createPixmapCursor(customCursor(cursorShape, screen));
default: default:
break; break;
} }
@ -555,7 +589,7 @@ CursorHandlePtr QWindowsCursor::standardWindowCursor(Qt::CursorShape shape)
{ {
StandardCursorCache::Iterator it = m_standardCursorCache.find(shape); StandardCursorCache::Iterator it = m_standardCursorCache.find(shape);
if (it == m_standardCursorCache.end()) { 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))); it = m_standardCursorCache.insert(shape, CursorHandlePtr(new CursorHandle(hc)));
} }
return it != m_standardCursorCache.end() ? it.value() : CursorHandlePtr(new CursorHandle); return it != m_standardCursorCache.end() ? it.value() : CursorHandlePtr(new CursorHandle);
@ -582,17 +616,21 @@ CursorHandlePtr QWindowsCursor::pixmapWindowCursor(const QCursor &c)
++it; ++it;
} }
} }
const qreal scaleFactor = QHighDpiScaling::factor(m_screen);
const QPixmap pixmap = c.pixmap(); const QPixmap pixmap = c.pixmap();
const HCURSOR hc = pixmap.isNull() 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))); it = m_pixmapCursorCache.insert(cacheKey, CursorHandlePtr(new CursorHandle(hc)));
} }
return it.value(); 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()); 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 \class QWindowsWindowCursor
\brief Per-Window cursor. Contains a QCursor and manages its associated system \brief Per-Window cursor. Contains a QCursor and manages its associated system

View File

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

View File

@ -269,13 +269,6 @@ QDebug operator<<(QDebug d, const QWindowsOleDropSource::CursorEntry &e)
} }
#endif // !QT_NO_DEBUG_STREAM #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. \brief Blend custom pixmap with cursors.
*/ */
@ -286,7 +279,17 @@ void QWindowsOleDropSource::createCursors()
const QPixmap pixmap = drag->pixmap(); const QPixmap pixmap = drag->pixmap();
const bool hasPixmap = !pixmap.isNull(); 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 const bool scalePixmap = hasPixmap
&& m_mode != TouchDrag // Touch drag: pixmap is shown in a separate QWindow, which will be scaled. && m_mode != TouchDrag // Touch drag: pixmap is shown in a separate QWindow, which will be scaled.
&& (scaleFactor != 1 && scaleFactor != qRound(pixmap.devicePixelRatio())); && (scaleFactor != 1 && scaleFactor != qRound(pixmap.devicePixelRatio()));
@ -304,8 +307,8 @@ void QWindowsOleDropSource::createCursors()
for (int cnum = 0; cnum < actionCount; ++cnum) { for (int cnum = 0; cnum < actionCount; ++cnum) {
const Qt::DropAction action = actions[cnum]; const Qt::DropAction action = actions[cnum];
QPixmap cursorPixmap = drag->dragCursor(action); QPixmap cursorPixmap = drag->dragCursor(action);
if (cursorPixmap.isNull()) if (cursorPixmap.isNull() && platformCursor)
cursorPixmap = m_drag->defaultCursor(action); cursorPixmap = static_cast<QWindowsCursor *>(platformCursor)->dragDefaultCursor(action);
const qint64 cacheKey = cursorPixmap.cacheKey(); const qint64 cacheKey = cursorPixmap.cacheKey();
const auto it = m_cursors.find(action); const auto it = m_cursors.find(action);
if (it != m_cursors.end() && it.value().cacheKey == cacheKey) if (it != m_cursors.end() && it.value().cacheKey == cacheKey)
@ -704,94 +707,6 @@ IDropTargetHelper* QWindowsDrag::dropHelper() {
return m_cachedDropTargetHelper; 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) Qt::DropAction QWindowsDrag::drag(QDrag *drag)
{ {
// TODO: Accessibility handling? // TODO: Accessibility handling?

View File

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

View File

@ -195,16 +195,6 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d)
} }
#endif // !QT_NO_DEBUG_STREAM #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 \class QWindowsScreen
\brief Windows screen. \brief Windows screen.
@ -216,7 +206,7 @@ static inline QSharedPointer<QPlatformCursor> sharedCursor()
QWindowsScreen::QWindowsScreen(const QWindowsScreenData &data) : QWindowsScreen::QWindowsScreen(const QWindowsScreenData &data) :
m_data(data) m_data(data)
#ifndef QT_NO_CURSOR #ifndef QT_NO_CURSOR
,m_cursor(sharedCursor()) , m_cursor(new QWindowsCursor(this))
#endif #endif
{ {
} }

View File

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

View File

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

View File

@ -1086,8 +1086,12 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
case XCB_FOCUS_OUT: case XCB_FOCUS_OUT:
HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent); HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent);
case XCB_KEY_PRESS: 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); HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent);
}
case XCB_KEY_RELEASE: case XCB_KEY_RELEASE:
m_keyboard->updateXKBStateFromCore(((xcb_key_release_event_t *)event)->state); m_keyboard->updateXKBStateFromCore(((xcb_key_release_event_t *)event)->state);
HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent); 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)) { for (; modesIter.rem; xcb_randr_mode_info_next(&modesIter)) {
xcb_randr_mode_info_t *modeInfo = modesIter.data; xcb_randr_mode_info_t *modeInfo = modesIter.data;
if (modeInfo->id == mode) { 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; m_mode = mode;
break; break;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1000,6 +1000,16 @@ void QPlatformTextureListWatcher::onLockStatusChanged(bool locked)
if (!isLocked()) if (!isLocked())
m_backingStore->sync(); m_backingStore->sync();
} }
#else
static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget)
{
Q_UNUSED(tlw);
Q_UNUSED(widget);
return Q_NULLPTR;
}
#endif // QT_NO_OPENGL #endif // QT_NO_OPENGL
static inline bool discardSyncRequest(QWidget *tlw, QTLWExtra *tlwExtra) static inline bool discardSyncRequest(QWidget *tlw, QTLWExtra *tlwExtra)
@ -1220,6 +1230,9 @@ void QWidgetBackingStore::doSync()
QWidget *w = static_cast<QWidget *>(tl->source(i)); QWidget *w = static_cast<QWidget *>(tl->source(i));
if (dirtyRenderToTextureWidgets.contains(w)) { if (dirtyRenderToTextureWidgets.contains(w)) {
const QRect rect = tl->geometry(i); // mapped to the tlw already 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; dirty += rect;
toClean += rect; toClean += rect;
} }

View File

@ -284,12 +284,6 @@ bool QSystemTrayIcon::isVisible() const
*/ */
bool QSystemTrayIcon::event(QEvent *e) 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); return QObject::event(e);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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