Merge "Merge remote-tracking branch 'origin/stable' into dev" into refs/staging/dev

bb10
Frederik Gladhorn 2014-05-13 14:27:45 +02:00 committed by The Qt Project
commit ff334fd574
91 changed files with 1212 additions and 381 deletions

9
dist/changes-5.3.0 vendored
View File

@ -446,6 +446,15 @@ Android
- Fonts:
* [QTBUG-36789] Fixed support for Arabic text.
iOS
---
- Support for input methods added.
- Support for word completion and spell checking added.
- Support for QClipboard added.
- "Hide keyboard" gesture added.
- Keyboard input is now sendt as input method events instead of key events.
Linux
-----

View File

@ -0,0 +1,27 @@
#
# W A R N I N G
# -------------
#
# This file is not part of the Qt API. It exists purely as an
# implementation detail. It may change from version to version
# without notice, or even be removed.
#
# We mean it.
#
load(qt_build_paths)
TEMPLATE = lib
CONFIG -= qt
contains(QT_CONFIG, debug_and_release): CONFIG += debug_and_release
contains(QT_CONFIG, build_all): CONFIG += build_all
DESTDIR = $$MODULE_BASE_OUTDIR/lib
DLLDESTDIR = $$MODULE_BASE_OUTDIR/bin
# Static builds always need to be installed, as the convenience libraries
# are not linked to the final library in this case.
installed|static: load(qt_installs)
TARGET = $$qtLibraryTarget($$TARGET)

View File

@ -18,7 +18,7 @@ QT_CPU_FEATURES = $$eval(QT_CPU_FEATURES.$$QT_ARCH)
#
# Set up compilers for SIMD (SSE/AVX, NEON etc)
#
*-g++*|intel_icc|*-clang*|*-qcc* {
gcc { # includes intel_icc and clang variants
sse2 {
HEADERS += $$SSE2_HEADERS

View File

@ -15,7 +15,7 @@ equals(TEMPLATE, app):contains(QT, gui(-private)?) {
# We do link and dependency resolution for the platform plugin
# manually, since we know we always need the plugin, so we don't
# need to generate an import for it.
CONFIG -= import_qpa_plugin
QTPLUGIN.platforms = -
!no_main_wrapper {
# We use ld to rename the _main symbol to _qt_main, so that we don't get a symbol clash

View File

@ -1116,7 +1116,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
//all files
const ProStringList &files = project->values(ProKey(bundle_data[i] + ".files"));
for(int file = 0; file < files.count(); file++) {
QString fn = files[file].toQString();
QString fn = fileFixify(files[file].toQString(), Option::output_dir, input_dir);
QString file_ref_key = keyFor("QMAKE_PBX_BUNDLE_DATA_FILE_REF." + bundle_data[i] + "-" + fn);
bundle_file_refs += file_ref_key;
t << "\t\t" << file_ref_key << " = {\n"

View File

@ -1745,14 +1745,14 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
if (target == TargetSuper) {
if (m_superfile.isEmpty()) {
m_superfile = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.super"));
printf("Info: creating super cache file %s\n", qPrintable(m_superfile));
printf("Info: creating super cache file %s\n", qPrintable(QDir::toNativeSeparators(m_superfile)));
valuesRef(ProKey("_QMAKE_SUPER_CACHE_")) << ProString(m_superfile);
}
fn = m_superfile;
} else if (target == TargetCache) {
if (m_cachefile.isEmpty()) {
m_cachefile = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.cache"));
printf("Info: creating cache file %s\n", qPrintable(m_cachefile));
printf("Info: creating cache file %s\n", qPrintable(QDir::toNativeSeparators(m_cachefile)));
valuesRef(ProKey("_QMAKE_CACHE_")) << ProString(m_cachefile);
// We could update m_{source,build}Root and m_featureRoots here, or even
// "re-home" our rootEnv, but this doesn't sound too useful - if somebody
@ -1766,7 +1766,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
if (fn.isEmpty())
fn = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.stash"));
if (!m_vfs->exists(fn)) {
printf("Info: creating stash file %s\n", qPrintable(fn));
printf("Info: creating stash file %s\n", qPrintable(QDir::toNativeSeparators(fn)));
valuesRef(ProKey("_QMAKE_STASH_")) << ProString(fn);
}
}

View File

@ -1,16 +1,11 @@
TARGET = qtharfbuzzng
TEMPLATE = lib
CONFIG += \
static \
hide_symbols \
exceptions_off rtti_off
CONFIG -= qt
contains(QT_CONFIG, debug_and_release):CONFIG += debug_and_release
contains(QT_CONFIG, build_all):CONFIG += build_all
DESTDIR = $$QT_BUILD_TREE/lib
load(qt_helper_lib)
DEFINES += HAVE_CONFIG_H
HEADERS += $$PWD/src/config.h
@ -133,5 +128,3 @@ mac {
# even in 10.8 where they were also made available stand-alone.
LIBS_PRIVATE += -framework ApplicationServices
}
TARGET = $$TARGET$$qtPlatformTargetSuffix()

View File

@ -690,13 +690,10 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
*/
CFDictionaryRef attributes = CTRunGetAttributes (run);
CTFontRef run_ct_font = static_cast<CTFontRef>(CFDictionaryGetValue (attributes, kCTFontAttributeName));
CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0);
CFRange range = CTRunGetStringRange (run);
if (!CFEqual (run_cg_font, face_data->cg_font))
if (!CFEqual (run_ct_font, font_data->ct_font))
{
CFRelease (run_cg_font);
buffer->ensure (buffer->len + range.length);
if (buffer->in_error)
FAIL ("Buffer resize failed");
@ -731,7 +728,6 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
}
continue;
}
CFRelease (run_cg_font);
/* CoreText throws away the PDF token, while the OpenType backend will add a zero-advance
* glyph for this. We need to make sure the two produce the same output. */

View File

@ -1,3 +1,4 @@
CONFIG += installed
include (../config.pri)
INCLUDEPATH += \

View File

@ -1,7 +1,4 @@
TEMPLATE = lib
CONFIG += static
TARGET = $$qtLibraryTarget(preprocessor)
include(../../config.pri)
INCLUDEPATH = $$ANGLE_DIR/src/compiler/preprocessor

View File

@ -1,7 +1,4 @@
TEMPLATE = lib
CONFIG += static
TARGET = $$qtLibraryTarget(translator)
include(../config.pri)
# Mingw 4.7 chokes on implicit move semantics, so disable C++11 here

View File

@ -59,17 +59,10 @@ CONFIG(debug, debug|release) {
}
# c++11 is needed by MinGW to get support for unordered_map.
CONFIG -= qt
CONFIG += stl exceptions c++11
contains(QT_CONFIG, debug_and_release):CONFIG += debug_and_release
contains(QT_CONFIG, build_all):CONFIG += build_all
INCLUDEPATH += . .. $$PWD/../include
DESTDIR = $$QT_BUILD_TREE/lib
DLLDESTDIR = $$QT_BUILD_TREE/bin
msvc {
# Disabled Warnings:
# 4100: 'identifier' : unreferenced formal parameter
@ -107,3 +100,5 @@ gcc {
QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE
load(qt_helper_lib)

View File

@ -1,9 +1,8 @@
TEMPLATE = lib
TARGET = $$qtLibraryTarget(d3dcompiler_qt)
TARGET = d3dcompiler_qt
CONFIG += installed
include(../config.pri)
CONFIG += qt
CONFIG += qt
QT = core
DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII
SOURCES += main.cpp
@ -16,5 +15,3 @@ winrt:equals(WINSDK_VER, 8.1) {
# __stdcall exports get mangled, so use a def file
DEF_FILE += $${TARGET}.def
load(qt_installs)

View File

@ -1,6 +1,4 @@
TEMPLATE = lib
TARGET = $$qtLibraryTarget(libEGL)
CONFIG += installed
include(../common/common.pri)
angle_d3d11: \
@ -30,8 +28,6 @@ SOURCES += \
mingw:equals(QT_ARCH, i386): DEF_FILE = $$ANGLE_DIR/src/libEGL/$${TARGET}_mingw32.def
}
load(qt_installs)
egl_headers.files = \
$$ANGLE_DIR/include/EGL/egl.h \
$$ANGLE_DIR/include/EGL/eglext.h \

View File

@ -1,7 +1,4 @@
TEMPLATE = lib
TARGET = $$qtLibraryTarget(libGLESv2)
CONFIG += simd
CONFIG += simd installed
include(../common/common.pri)
INCLUDEPATH += $$OUT_PWD/.. $$ANGLE_DIR/src/libGLESv2
@ -13,8 +10,8 @@ angle_d3d11: \
LIBS_PRIVATE += -ld3d9
LIBS_PRIVATE += -ldxguid
STATICLIBS = translator preprocessor
STATICLIBS = translator preprocessor
for(libname, STATICLIBS) {
# Appends 'd' to the library for debug builds and builds up the fully
# qualified path to pass to the linker.
@ -238,8 +235,6 @@ for (vs, VERTEX_SHADERS_CLEAR) {
angle_d3d11: QMAKE_EXTRA_COMPILERS += fxc_vs_$${vs}
}
load(qt_installs)
khr_headers.files = $$ANGLE_DIR/include/KHR/khrplatform.h
khr_headers.path = $$[QT_INSTALL_HEADERS]/QtANGLE/KHR
gles2_headers.files = \
@ -248,5 +243,3 @@ gles2_headers.files = \
$$ANGLE_DIR/include/GLES2/gl2platform.h
gles2_headers.path = $$[QT_INSTALL_HEADERS]/QtANGLE/GLES2
INSTALLS += khr_headers gles2_headers

View File

@ -26,7 +26,8 @@ qhp.QtCore.subprojects.classes.sortPages = true
tagfile = ../../../doc/qtcore/qtcore.tags
depends += activeqt qtdbus qtgui qtwidgets qtnetwork qtdoc qtmacextras qtqml qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake
depends += activeqt qtdbus qtgui qtwidgets qtnetwork qtdoc qtmacextras qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake
# depends += qtqml # Qt namespace collides with QtQml::Qt, see QTBUG-38630
headerdirs += ..

View File

@ -362,6 +362,11 @@ QStringList QFileSelectorPrivate::platformSelectors()
ret << QStringLiteral("windows");
# if defined(Q_OS_WINCE)
ret << QStringLiteral("wince");
# elif defined(Q_OS_WINRT)
ret << QStringLiteral("winrt");
# if defined(Q_OS_WINPHONE)
ret << QStringLiteral("winphone");
# endif
# endif
#elif defined(Q_OS_UNIX)
ret << QStringLiteral("unix");

View File

@ -62,6 +62,12 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
by a string - at runtime. Whether a category should be actually logged or
not can be checked with the \l isEnabled() methods.
All objects are meant to be configured by a common registry (see also
\l{Configuring Categories}). Different objects can also represent the same
category. It's therefore not recommended to export objects across module
boundaries, nor to manipulate the objects directly, nor to inherit from
QLoggingCategory.
\section1 Creating category objects
The Q_LOGGING_CATEGORY() and the Q_DECLARE_LOGGING_CATEGORY() macros

View File

@ -325,6 +325,7 @@ private:
friend class QGraphicsViewPrivate;
friend class QGraphicsScene;
friend class QGraphicsScenePrivate;
friend class QWidgetWindow;
#ifndef QT_NO_GESTURES
friend class QGestureManager;
#endif

View File

@ -777,6 +777,7 @@ struct VariantData
const void *data;
const uint flags;
private:
// copy constructor allowed to be implicit to silence level 4 warning from MSVC
VariantData &operator=(const VariantData &) Q_DECL_EQ_DELETE;
};

View File

@ -125,11 +125,9 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
or writing to the shared memory, and remember to release the lock
with unlock() after you are done.
Unlike QtSharedMemory, QSharedMemory automatically destroys the
shared memory segment when the last instance of QSharedMemory is
detached from the segment, and no references to the segment
remain. Do not mix using QtSharedMemory and QSharedMemory. Port
everything to QSharedMemory.
QSharedMemory automatically destroys the shared memory segment when
the last instance of QSharedMemory is detached from the segment, and
no references to the segment remain.
\warning QSharedMemory changes the key in a Qt-specific way, unless otherwise
specified. Interoperation with non-Qt applications is achieved by first creating

View File

@ -89,7 +89,7 @@ QTimeZonePrivate *QMacTimeZonePrivate::clone()
void QMacTimeZonePrivate::init(const QByteArray &ianaId)
{
if (availableTimeZoneIds().contains(ianaId)) {
m_nstz = [NSTimeZone timeZoneWithName:QCFString::toNSString(QString::fromUtf8(ianaId))];
m_nstz = [[NSTimeZone timeZoneWithName:QCFString::toNSString(QString::fromUtf8(ianaId))] retain];
if (m_nstz)
m_id = ianaId;
}
@ -142,7 +142,6 @@ QString QMacTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
NSString *macLocaleCode = QCFString::toNSString(locale.name());
NSLocale *macLocale = [[NSLocale alloc] initWithLocaleIdentifier:macLocaleCode];
const QString result = QCFString::toQString([m_nstz localizedName:style locale:macLocale]);
[macLocaleCode release];
[macLocale release];
return result;
}
@ -192,7 +191,6 @@ QTimeZonePrivate::Data QMacTimeZonePrivate::data(qint64 forMSecsSinceEpoch) cons
data.daylightTimeOffset = [m_nstz daylightSavingTimeOffsetForDate:date];
data.standardTimeOffset = data.offsetFromUtc - data.daylightTimeOffset;
data.abbreviation = QCFString::toQString([m_nstz abbreviationForDate:date]);
[date release];
return data;
}
@ -203,8 +201,6 @@ bool QMacTimeZonePrivate::hasTransitions() const
NSDate *epoch = [NSDate dateWithTimeIntervalSince1970:0];
const NSDate *date = [m_nstz nextDaylightSavingTimeTransitionAfterDate:epoch];
const bool result = ([date timeIntervalSince1970] > [epoch timeIntervalSince1970]);
[epoch release];
[date release];
return result;
}
@ -224,7 +220,6 @@ QTimeZonePrivate::Data QMacTimeZonePrivate::nextTransition(qint64 afterMSecsSinc
tran.daylightTimeOffset = [m_nstz daylightSavingTimeOffsetForDate:nextDate];
tran.standardTimeOffset = tran.offsetFromUtc - tran.daylightTimeOffset;
tran.abbreviation = QCFString::toQString([m_nstz abbreviationForDate:nextDate]);
[nextDate release];
return tran;
}
@ -246,7 +241,6 @@ QTimeZonePrivate::Data QMacTimeZonePrivate::previousTransition(qint64 beforeMSec
nextDate = [m_nstz nextDaylightSavingTimeTransitionAfterDate:nextDate];
nextSecs = [nextDate timeIntervalSince1970];
}
[nextDate release];
}
if (secsList.size() >= 1)
return data(qint64(secsList.last()) * 1000);

View File

@ -59,6 +59,7 @@ static int global_ser_no = 0;
QBlittablePlatformPixmap::QBlittablePlatformPixmap()
: QPlatformPixmap(QPlatformPixmap::PixmapType,BlitterClass)
, m_alpha(false)
, m_devicePixelRatio(1.0)
#ifdef QT_BLITTER_RASTEROVERLAY
,m_rasterOverlay(0), m_unmergedCopy(0)
#endif //QT_BLITTER_RASTEROVERLAY
@ -121,7 +122,7 @@ int QBlittablePlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) con
case QPaintDevice::PdmPhysicalDpiY:
return qt_defaultDpiY();
case QPaintDevice::PdmDevicePixelRatio:
return 1;
return devicePixelRatio();
default:
qWarning("QRasterPlatformPixmap::metric(): Unhandled metric type %d", metric);
break;
@ -178,6 +179,7 @@ void QBlittablePlatformPixmap::fromImage(const QImage &image,
Qt::ImageConversionFlags flags)
{
m_alpha = image.hasAlphaChannel();
m_devicePixelRatio = image.devicePixelRatio();
resize(image.width(),image.height());
markRasterOverlay(QRect(0,0,w,h));
QImage *thisImg = buffer();

View File

@ -199,19 +199,13 @@ public:
enum OpenGLModuleType {
LibGL,
LibGLES,
// ###
DesktopGL = LibGL,
GLES2 = LibGLES
LibGLES
};
static OpenGLModuleType openGLModuleType();
bool isOpenGLES() const;
bool isES() const { return isOpenGLES(); } // ###
Q_SIGNALS:
void aboutToBeDestroyed();

View File

@ -297,7 +297,7 @@ Q_SIGNALS:
void screenChanged(QScreen *screen);
void modalityChanged(Qt::WindowModality modality);
void windowStateChanged(Qt::WindowState windowState);
void windowTitleChanged(const QString &title);
Q_REVISION(2) void windowTitleChanged(const QString &title);
void xChanged(int arg);
void yChanged(int arg);

View File

@ -1112,6 +1112,9 @@ Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format,
\fn QImage QOpenGLFramebufferObject::toImage() const
Returns the contents of this framebuffer object as a QImage.
Will try to return a premultiplied ARBG32 or RGB32 image. Since 5.2 it will fall back to
a premultiplied RGBA8888 or RGBx8888 image when reading to ARGB32 is not supported.
*/
QImage QOpenGLFramebufferObject::toImage() const
{

View File

@ -1709,6 +1709,163 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c
}
} else {
//we are zooming less than 8x, use 4bit precision
if (blendType != BlendTransformedBilinearTiled) {
#define BILINEAR_ROTATE_BOUNDS_PROLOG \
while (b < end) { \
int x1 = (fx >> 16); \
int x2; \
int y1 = (fy >> 16); \
int y2; \
fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); \
fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); \
if (x1 != x2 && y1 != y2) \
break; \
const uint *s1 = (const uint *)data->texture.scanLine(y1); \
const uint *s2 = (const uint *)data->texture.scanLine(y2); \
uint tl = s1[x1]; \
uint tr = s1[x2]; \
uint bl = s2[x1]; \
uint br = s2[x2]; \
int distx = (fx & 0x0000ffff) >> 12; \
int disty = (fy & 0x0000ffff) >> 12; \
*b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); \
fx += fdx; \
fy += fdy; \
++b; \
} \
uint *boundedEnd = end - 3; \
boundedEnd -= 3;
#if defined(__SSE2__)
BILINEAR_ROTATE_BOUNDS_PROLOG
const __m128i colorMask = _mm_set1_epi32(0x00ff00ff);
const __m128i v_256 = _mm_set1_epi16(256);
__m128i v_fdx = _mm_set1_epi32(fdx*4);
__m128i v_fdy = _mm_set1_epi32(fdy*4);
const uchar *textureData = data->texture.imageData;
const int bytesPerLine = data->texture.bytesPerLine;
union Vect_buffer { __m128i vect; qint32 i[4]; };
Vect_buffer v_fx, v_fy;
for (int i = 0; i < 4; i++) {
v_fx.i[i] = fx;
v_fy.i[i] = fy;
fx += fdx;
fy += fdy;
}
while (b < boundedEnd) {
if (fdx > 0 && (v_fx.i[3] >> 16) >= image_x2)
break;
if (fdx < 0 && (v_fx.i[3] >> 16) < image_x1)
break;
if (fdy > 0 && (v_fy.i[3] >> 16) >= image_y2)
break;
if (fdy < 0 && (v_fy.i[3] >> 16) < image_y1)
break;
Vect_buffer tl, tr, bl, br;
Vect_buffer v_fx_shifted, v_fy_shifted;
v_fx_shifted.vect = _mm_srli_epi32(v_fx.vect, 16);
v_fy_shifted.vect = _mm_srli_epi32(v_fy.vect, 16);
for (int i = 0; i < 4; i++) {
const int x1 = v_fx_shifted.i[i];
const int y1 = v_fy_shifted.i[i];
const uchar *sl = textureData + bytesPerLine * y1;
const uint *s1 = (const uint *)sl;
const uint *s2 = (const uint *)(sl + bytesPerLine);
tl.i[i] = s1[x1];
tr.i[i] = s1[x1+1];
bl.i[i] = s2[x1];
br.i[i] = s2[x1+1];
}
__m128i v_distx = _mm_srli_epi16(v_fx.vect, 12);
__m128i v_disty = _mm_srli_epi16(v_fy.vect, 12);
v_distx = _mm_shufflehi_epi16(v_distx, _MM_SHUFFLE(2,2,0,0));
v_distx = _mm_shufflelo_epi16(v_distx, _MM_SHUFFLE(2,2,0,0));
v_disty = _mm_shufflehi_epi16(v_disty, _MM_SHUFFLE(2,2,0,0));
v_disty = _mm_shufflelo_epi16(v_disty, _MM_SHUFFLE(2,2,0,0));
interpolate_4_pixels_16_sse2(tl.vect, tr.vect, bl.vect, br.vect, v_distx, v_disty, colorMask, v_256, b);
b+=4;
v_fx.vect = _mm_add_epi32(v_fx.vect, v_fdx);
v_fy.vect = _mm_add_epi32(v_fy.vect, v_fdy);
}
fx = v_fx.i[0];
fy = v_fy.i[0];
#elif defined(__ARM_NEON__)
BILINEAR_ROTATE_BOUNDS_PROLOG
const int16x8_t colorMask = vdupq_n_s16(0x00ff);
const int16x8_t invColorMask = vmvnq_s16(colorMask);
const int16x8_t v_256 = vdupq_n_s16(256);
int32x4_t v_fdx = vdupq_n_s32(fdx*4);
int32x4_t v_fdy = vdupq_n_s32(fdy*4);
const uchar *textureData = data->texture.imageData;
const int bytesPerLine = data->texture.bytesPerLine;
union Vect_buffer { int32x4_t vect; quint32 i[4]; };
Vect_buffer v_fx, v_fy;
for (int i = 0; i < 4; i++) {
v_fx.i[i] = fx;
v_fy.i[i] = fy;
fx += fdx;
fy += fdy;
}
const int32x4_t v_ffff_mask = vdupq_n_s32(0x0000ffff);
while (b < boundedEnd) {
if (fdx > 0 && (v_fx.i[3] >> 16) >= image_x2)
break;
if (fdx < 0 && (v_fx.i[3] >> 16) < image_x1)
break;
if (fdy > 0 && (v_fy.i[3] >> 16) >= image_y2)
break;
if (fdy < 0 && (v_fy.i[3] >> 16) < image_y1)
break;
Vect_buffer tl, tr, bl, br;
Vect_buffer v_fx_shifted, v_fy_shifted;
v_fx_shifted.vect = vshrq_n_s32(v_fx.vect, 16);
v_fy_shifted.vect = vshrq_n_s32(v_fy.vect, 16);
for (int i = 0; i < 4; i++) {
const int x1 = v_fx_shifted.i[i];
const int y1 = v_fy_shifted.i[i];
const uchar *sl = textureData + bytesPerLine * y1;
const uint *s1 = (const uint *)sl;
const uint *s2 = (const uint *)(sl + bytesPerLine);
tl.i[i] = s1[x1];
tr.i[i] = s1[x1+1];
bl.i[i] = s2[x1];
br.i[i] = s2[x1+1];
}
int32x4_t v_distx = vshrq_n_s32(vandq_s32(v_fx.vect, v_ffff_mask), 12);
int32x4_t v_disty = vshrq_n_s32(vandq_s32(v_fy.vect, v_ffff_mask), 12);
v_distx = vorrq_s32(v_distx, vshlq_n_s32(v_distx, 16));
v_disty = vorrq_s32(v_disty, vshlq_n_s32(v_disty, 16));
int16x8_t v_disty_ = vshlq_n_s16(v_disty, 4);
interpolate_4_pixels_16_neon(vreinterpretq_s16_s32(tl.vect), vreinterpretq_s16_s32(tr.vect), vreinterpretq_s16_s32(bl.vect), vreinterpretq_s16_s32(br.vect), vreinterpretq_s16_s32(v_distx), v_disty, v_disty_, colorMask, invColorMask, v_256, b);
b+=4;
v_fx.vect = vaddq_s32(v_fx.vect, v_fdx);
v_fy.vect = vaddq_s32(v_fy.vect, v_fdy);
}
fx = v_fx.i[0];
fy = v_fy.i[0];
#endif
}
while (b < end) {
int x1 = (fx >> 16);
int x2;

View File

@ -147,8 +147,9 @@ static inline uint line_emulation(uint emulation)
}
#ifndef QT_NO_DEBUG
static bool qt_painter_thread_test(int devType, const char *what)
static bool qt_painter_thread_test(int devType, int engineType, const char *what)
{
const QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
switch (devType) {
case QInternal::Image:
case QInternal::Printer:
@ -157,8 +158,13 @@ static bool qt_painter_thread_test(int devType, const char *what)
break;
default:
if (QThread::currentThread() != qApp->thread()
&& (devType!=QInternal::Pixmap || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedPixmaps))
&& (devType!=QInternal::OpenGL || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedOpenGL))) {
// pixmaps cannot be targets unless threaded pixmaps are supported
&& (devType != QInternal::Pixmap || !platformIntegration->hasCapability(QPlatformIntegration::ThreadedPixmaps))
// framebuffer objects and such cannot be targets unless threaded GL is supported
&& (devType != QInternal::OpenGL || !platformIntegration->hasCapability(QPlatformIntegration::ThreadedOpenGL))
// widgets cannot be targets except for QGLWidget
&& (devType != QInternal::Widget || !platformIntegration->hasCapability(QPlatformIntegration::ThreadedOpenGL)
|| (engineType != QPaintEngine::OpenGL && engineType != QPaintEngine::OpenGL2))) {
qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
return false;
}
@ -5054,7 +5060,7 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
return;
#ifndef QT_NO_DEBUG
qt_painter_thread_test(d->device->devType(), "drawPixmap()");
qt_painter_thread_test(d->device->devType(), d->engine->type(), "drawPixmap()");
#endif
if (d->extended) {
@ -5125,7 +5131,7 @@ void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
if (!d->engine || pm.isNull())
return;
#ifndef QT_NO_DEBUG
qt_painter_thread_test(d->device->devType(), "drawPixmap()");
qt_painter_thread_test(d->device->devType(), d->engine->type(), "drawPixmap()");
#endif
qreal x = r.x();
@ -6612,7 +6618,7 @@ void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPo
return;
#ifndef QT_NO_DEBUG
qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()");
qt_painter_thread_test(d->device->devType(), d->engine->type(), "drawTiledPixmap()");
#endif
qreal sw = pixmap.width();

View File

@ -1335,6 +1335,15 @@ QByteArray QFontEngine::convertToPostscriptFontFamilyName(const QByteArray &fami
return f;
}
/**
* Some font engines like the windows font engine
* can not reliable create outline paths
*/
bool QFontEngine::hasUnreliableGlyphOutline() const
{
return false;
}
QFixed QFontEngine::lastRightBearing(const QGlyphLayout &glyphs, bool round)
{
if (glyphs.numGlyphs >= 1) {

View File

@ -450,6 +450,7 @@ static void scaleOutline(FT_Face face, FT_GlyphSlot g, FT_Fixed x_scale, FT_Fixe
}
}
#define GLYPH2PATH_DEBUG QT_NO_QDEBUG_MACRO // qDebug
void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, FT_Fixed x_scale, FT_Fixed y_scale)
{
const qreal factor = 1/64.;
@ -461,22 +462,32 @@ void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoi
int i = 0;
for (int j = 0; j < g->outline.n_contours; ++j) {
int last_point = g->outline.contours[j];
QPointF start = cp + QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor);
if(!(g->outline.tags[i] & 1)) {
start += cp + QPointF(g->outline.points[last_point].x*factor, -g->outline.points[last_point].y*factor);
start /= 2;
GLYPH2PATH_DEBUG() << "contour:" << i << "to" << last_point;
QPointF start = QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor);
if (!(g->outline.tags[i] & 1)) { // start point is not on curve:
if (!(g->outline.tags[last_point] & 1)) { // end point is not on curve:
GLYPH2PATH_DEBUG() << " start and end point are not on curve";
start = (QPointF(g->outline.points[last_point].x*factor,
-g->outline.points[last_point].y*factor) + start) / 2.0;
} else {
GLYPH2PATH_DEBUG() << " end point is on curve, start is not";
start = QPointF(g->outline.points[last_point].x*factor,
-g->outline.points[last_point].y*factor);
}
--i; // to use original start point as control point below
}
// qDebug("contour: %d -- %d", i, g->outline.contours[j]);
// qDebug("first point at %f %f", start.x(), start.y());
path->moveTo(start);
start += cp;
GLYPH2PATH_DEBUG() << " start at" << start;
path->moveTo(start);
QPointF c[4];
c[0] = start;
int n = 1;
while (i < last_point) {
++i;
c[n] = cp + QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor);
// qDebug() << " i=" << i << " flag=" << (int)g->outline.tags[i] << "point=" << c[n];
GLYPH2PATH_DEBUG() << " " << i << c[n] << "tag =" << (int)g->outline.tags[i]
<< ": on curve =" << (bool)(g->outline.tags[i] & 1);
++n;
switch (g->outline.tags[i] & 3) {
case 2:
@ -498,7 +509,7 @@ void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoi
case 1:
case 3:
if (n == 2) {
// qDebug() << "lineTo" << c[1];
GLYPH2PATH_DEBUG() << " lineTo" << c[1];
path->lineTo(c[1]);
c[0] = c[1];
n = 1;
@ -510,13 +521,14 @@ void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoi
}
break;
}
// qDebug() << "cubicTo" << c[1] << c[2] << c[3];
GLYPH2PATH_DEBUG() << " cubicTo" << c[1] << c[2] << c[3];
path->cubicTo(c[1], c[2], c[3]);
c[0] = c[3];
n = 1;
}
if (n == 1) {
// qDebug() << "closeSubpath";
GLYPH2PATH_DEBUG() << " closeSubpath";
path->closeSubpath();
} else {
c[3] = start;
@ -524,7 +536,7 @@ void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoi
c[2] = (2*c[1] + c[3])/3;
c[1] = (2*c[1] + c[0])/3;
}
// qDebug() << "cubicTo" << c[1] << c[2] << c[3];
GLYPH2PATH_DEBUG() << " close cubicTo" << c[1] << c[2] << c[3];
path->cubicTo(c[1], c[2], c[3]);
}
++i;

View File

@ -251,6 +251,8 @@ public:
static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily);
virtual bool hasUnreliableGlyphOutline() const;
enum HintStyle {
HintNone,
HintLight,

View File

@ -132,7 +132,7 @@ QTextCursorPrivate::AdjustResult QTextCursorPrivate::adjustPosition(int position
void QTextCursorPrivate::setX()
{
if (priv->isInEditBlock()) {
if (priv->isInEditBlock() || priv->inContentsChange) {
x = -1; // mark dirty
return;
}

View File

@ -2057,7 +2057,7 @@ void QTextEngine::justify(const QScriptLine &line)
// subtract one char more, as we can't justfy after the last character
--line_length;
if (!line_length)
if (line_length <= 0)
return;
int firstItem = findItem(line.from);

View File

@ -509,7 +509,7 @@ static QByteArray qt_prettyDebug(const char *data, int len, int maxLength)
{
if (!data) return "(null)";
QByteArray out;
for (int i = 0; i < len; ++i) {
for (int i = 0; i < qMin(len, maxLength); ++i) {
char c = data[i];
if (isprint(int(uchar(c)))) {
out += c;

View File

@ -69,7 +69,8 @@ QEGLPlatformCursor::QEGLPlatformCursor(QPlatformScreen *screen)
m_vertexCoordEntry(0),
m_textureCoordEntry(0),
m_textureEntry(0),
m_deviceListener(0)
m_deviceListener(0),
m_updater(screen)
{
QByteArray hideCursorVal = qgetenv("QT_QPA_EGLFS_HIDECURSOR");
if (!hideCursorVal.isEmpty())
@ -270,10 +271,30 @@ bool QEGLPlatformCursor::setCurrentCursor(QCursor *cursor)
}
#endif
void QEGLPlatformCursorUpdater::update(const QPoint &pos, const QRegion &rgn)
{
m_active = false;
QWindowSystemInterface::handleExposeEvent(m_screen->topLevelAt(pos), rgn);
QWindowSystemInterface::flushWindowSystemEvents();
}
void QEGLPlatformCursorUpdater::scheduleUpdate(const QPoint &pos, const QRegion &rgn)
{
if (m_active)
return;
m_active = true;
// Must not flush the window system events directly from here since we are likely to
// be a called directly from QGuiApplication's processMouseEvents. Flushing events
// could cause reentering by dispatching more queued mouse events.
QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection,
Q_ARG(QPoint, pos), Q_ARG(QRegion, rgn));
}
void QEGLPlatformCursor::update(const QRegion &rgn)
{
QWindowSystemInterface::handleExposeEvent(m_screen->topLevelAt(m_cursor.pos), rgn);
QWindowSystemInterface::flushWindowSystemEvents();
m_updater.scheduleUpdate(m_cursor.pos, rgn);
}
QRect QEGLPlatformCursor::cursorRect() const

View File

@ -68,6 +68,24 @@ private:
int m_mouseCount;
};
class QEGLPlatformCursorUpdater : public QObject
{
Q_OBJECT
public:
QEGLPlatformCursorUpdater(QPlatformScreen *screen)
: m_screen(screen), m_active(false) { }
void scheduleUpdate(const QPoint &pos, const QRegion &rgn);
private slots:
void update(const QPoint &pos, const QRegion &rgn);
private:
QPlatformScreen *m_screen;
bool m_active;
};
class QEGLPlatformCursor : public QPlatformCursor
{
public:
@ -130,6 +148,7 @@ private:
int m_textureCoordEntry;
int m_textureEntry;
QEGLPlatformCursorDeviceListener *m_deviceListener;
QEGLPlatformCursorUpdater m_updater;
};
QT_END_NAMESPACE

View File

@ -50,7 +50,7 @@
#include "qdebug.h"
static const char m_qtTag[] = "QtA11y";
static const char m_qtTag[] = "Qt A11Y";
static const char m_classErrorMsg[] = "Can't find class \"%s\"";
static const char m_methodErrorMsg[] = "Can't find method \"%s%s\"";
@ -184,8 +184,6 @@ if (!clazz) { \
desc = iface->text(QAccessible::Name);
if (desc.isEmpty())
desc = iface->text(QAccessible::Description);
desc += QChar(' ') + QString::fromUtf8(qAccessibleRoleString(iface->role()));
}
jstring jdesc = env->NewString((jchar*) desc.constData(), (jsize) desc.size());
@ -216,12 +214,6 @@ if (!clazz) { \
}
}
if ((iface->role() != QAccessible::NoRole) &&
(iface->role() != QAccessible::Client) &&
(iface->role() != QAccessible::Pane)) {
desc += QChar(' ') + QString::fromUtf8(qAccessibleRoleString(iface->role()));
}
CALL_METHOD(node, "setEnabled", "(Z)V", !state.disabled)
//CALL_METHOD(node, "setFocusable", "(Z)V", state.focusable)
CALL_METHOD(node, "setFocusable", "(Z)V", true)

View File

@ -769,7 +769,6 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
|| !QtAndroidInput::registerNatives(env)
|| !QtAndroidClipboard::registerNatives(env)
|| !QtAndroidMenu::registerNatives(env)
|| !QtAndroidAccessibility::registerNatives(env)
|| !QtAndroidDialogHelpers::registerNatives(env)) {
__android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed");
return -1;

View File

@ -591,19 +591,37 @@ jboolean QAndroidInputContext::endBatchEdit()
return JNI_TRUE;
}
jboolean QAndroidInputContext::commitText(const QString &text, jint /*newCursorPosition*/)
/*
Android docs say: If composing, replace compose text with \a text.
Otherwise insert \a text at current cursor position.
The cursor should then be moved to newCursorPosition. If > 0, this is
relative to the end of the text - 1; if <= 0, this is relative to the start
of the text. updateSelection() needs to be called.
*/
jboolean QAndroidInputContext::commitText(const QString &text, jint newCursorPosition)
{
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
return JNI_FALSE;
QInputMethodEvent event;
event.setCommitString(text);
sendInputMethodEvent(&event);
clear();
// Qt has now put the cursor at the end of the text, corresponding to newCursorPosition == 1
if (newCursorPosition != 1) {
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (!query.isNull()) {
QList<QInputMethodEvent::Attribute> attributes;
const int localPos = query->value(Qt::ImCursorPosition).toInt();
const int newLocalPos = newCursorPosition > 0
? localPos + newCursorPosition - 1
: localPos - text.length() + newCursorPosition;
//move the cursor
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection,
newLocalPos, 0, QVariant()));
}
}
const int cursorPos = getAbsoluteCursorPosition(query);
m_composingText = text;
m_composingTextStart = cursorPos;
m_composingCursor = cursorPos + text.length();
finishComposingText();
//### move cursor to newCursorPosition and call updateCursorPosition()
updateCursorPosition();
return JNI_TRUE;
}
@ -624,9 +642,24 @@ jboolean QAndroidInputContext::deleteSurroundingText(jint leftLength, jint right
return JNI_TRUE;
}
// Android docs say the cursor must not move
jboolean QAndroidInputContext::finishComposingText()
{
QInputMethodEvent event;
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
return JNI_FALSE;
if (m_composingText.isEmpty())
return JNI_TRUE; // not composing
const int blockPos = getBlockPosition(query);
const int localCursorPos = m_composingCursor - blockPos;
// Moving Qt's cursor to where the preedit cursor used to be
QList<QInputMethodEvent::Attribute> attributes;
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, localCursorPos, 0, QVariant()));
QInputMethodEvent event(QString(), attributes);
event.setCommitString(m_composingText);
sendInputMethodEvent(&event);
clear();

View File

@ -92,16 +92,20 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
QFont newFont;
if (cocoaFont) {
int pSize = qRound([cocoaFont pointSize]);
CTFontDescriptorRef font = CTFontCopyFontDescriptor((CTFontRef)cocoaFont);
// QCoreTextFontDatabase::populateFontDatabase() is using localized names
QString family = QCFString::toQString((CFStringRef) CTFontDescriptorCopyLocalizedAttribute(font, kCTFontFamilyNameAttribute, NULL));
QString style = QCFString::toQString((CFStringRef) CTFontDescriptorCopyLocalizedAttribute(font, kCTFontStyleNameAttribute, NULL));
QString family(QCFString::toQString([cocoaFont familyName]));
QString typeface(QCFString::toQString([cocoaFont fontName]));
newFont = QFontDatabase().font(family, style, pSize);
int hyphenPos = typeface.indexOf(QLatin1Char('-'));
if (hyphenPos != -1) {
typeface.remove(0, hyphenPos + 1);
} else {
typeface = QLatin1String("Normal");
}
newFont = QFontDatabase().font(family, typeface, pSize);
newFont.setUnderline(resolveFont.underline());
newFont.setStrikeOut(resolveFont.strikeOut());
CFRelease(font);
}
return newFont;
}

View File

@ -234,6 +234,10 @@ QCocoaMenu::QCocoaMenu() :
QCocoaMenu::~QCocoaMenu()
{
foreach (QCocoaMenuItem *item, m_menuItems) {
if (COCOA_MENU_ANCESTOR(item) == this)
SET_COCOA_MENU_ANCESTOR(item, 0);
}
QCocoaAutoReleasePool pool;
[m_nativeItem setSubmenu:nil];
[m_nativeMenu release];

View File

@ -106,6 +106,8 @@ QCocoaMenuItem::QCocoaMenuItem() :
QCocoaMenuItem::~QCocoaMenuItem()
{
if (m_menu && COCOA_MENU_ANCESTOR(m_menu) == this)
SET_COCOA_MENU_ANCESTOR(m_menu, 0);
if (m_merged) {
[m_native setHidden:YES];
} else {

View File

@ -463,7 +463,11 @@ bool QCocoaPrintDevice::openPpdFile()
ppdClose(m_ppd);
m_ppd = 0;
CFURLRef ppdURL = NULL;
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
char ppdPath[PATH_MAX];
#else
char ppdPath[MAXPATHLEN];
#endif
if (PMPrinterCopyDescriptionURL(m_printer, kPMPPDDescriptionType, &ppdURL) == noErr
&& ppdURL != NULL
&& CFURLGetFileSystemRepresentation(ppdURL, true, (UInt8*)ppdPath, sizeof(ppdPath))) {

View File

@ -9,7 +9,7 @@ QT *= core-private
QT *= gui-private
QT *= platformsupport-private
LIBS *= -ld2d1 -ld3d11 -ldwrite
LIBS *= -ld2d1 -ld3d11 -ldwrite -lVersion
include(../windows/windows.pri)

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@ -66,6 +66,16 @@ static inline QWindowsDirect2DPlatformPixmap *platformPixmap(QPixmap *p)
return static_cast<QWindowsDirect2DPlatformPixmap *>(p->handle());
}
static inline QWindowsDirect2DBitmap *bitmap(QPixmap *p)
{
return platformPixmap(p)->bitmap();
}
static inline QWindowsDirect2DWindow *nativeWindow(QWindow *window)
{
return static_cast<QWindowsDirect2DWindow *>(window->handle());
}
QWindowsDirect2DBackingStore::QWindowsDirect2DBackingStore(QWindow *window)
: QPlatformBackingStore(window)
{
@ -77,36 +87,40 @@ QWindowsDirect2DBackingStore::~QWindowsDirect2DBackingStore()
void QWindowsDirect2DBackingStore::beginPaint(const QRegion &)
{
platformPixmap(m_pixmap.data())->bitmap()->deviceContext()->begin();
bitmap(nativeWindow(window())->pixmap())->deviceContext()->begin();
}
void QWindowsDirect2DBackingStore::endPaint()
{
platformPixmap(m_pixmap.data())->bitmap()->deviceContext()->end();
bitmap(nativeWindow(window())->pixmap())->deviceContext()->end();
}
QPaintDevice *QWindowsDirect2DBackingStore::paintDevice()
{
return m_pixmap.data();
return nativeWindow(window())->pixmap();
}
void QWindowsDirect2DBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
void QWindowsDirect2DBackingStore::flush(QWindow *targetWindow, const QRegion &region, const QPoint &offset)
{
QPlatformWindow *pw = window->handle();
if (pw && m_pixmap)
static_cast<QWindowsDirect2DWindow *>(pw)->flush(platformPixmap(m_pixmap.data())->bitmap(), region, offset);
if (targetWindow != window()) {
QSharedPointer<QWindowsDirect2DBitmap> copy(nativeWindow(window())->copyBackBuffer());
nativeWindow(targetWindow)->flush(copy.data(), region, offset);
}
nativeWindow(targetWindow)->present();
}
void QWindowsDirect2DBackingStore::resize(const QSize &size, const QRegion &region)
{
Q_UNUSED(region);
QPixmap old = nativeWindow(window())->pixmap()->copy();
QScopedPointer<QPixmap> oldPixmap(m_pixmap.take());
m_pixmap.reset(new QPixmap(size.width(), size.height()));
nativeWindow(window())->resizeSwapChain(size);
QPixmap *newPixmap = nativeWindow(window())->pixmap();
if (oldPixmap) {
foreach (const QRect &rect, region.rects())
platformPixmap(m_pixmap.data())->copy(oldPixmap->handle(), rect);
if (!old.isNull()) {
foreach (const QRect &rect, region.rects()) {
platformPixmap(newPixmap)->copy(old.handle(), rect);
}
}
}

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@ -50,6 +50,8 @@
QT_BEGIN_NAMESPACE
class QWindowsDirect2DWindow;
class QWindowsDirect2DBackingStore : public QPlatformBackingStore
{
Q_DISABLE_COPY(QWindowsDirect2DBackingStore)
@ -62,11 +64,8 @@ public:
void endPaint();
QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
void flush(QWindow *window, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
void flush(QWindow *targetWindow, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE;
private:
QScopedPointer<QPixmap> m_pixmap;
};
QT_END_NAMESPACE

View File

@ -99,7 +99,7 @@ public:
return false;
}
hr = dxgiDevice->GetParent(IID_PPV_ARGS(&dxgiAdapter));
hr = dxgiDevice->GetAdapter(&dxgiAdapter);
if (FAILED(hr)) {
qWarning("%s: Failed to probe DXGI Device for parent DXGI Adapter: %#x", __FUNCTION__, hr);
return false;

View File

@ -48,7 +48,8 @@
#include "qwindowscontext.h"
#include <QtCore/QDebug>
#include <qplatformdefs.h>
#include <QtCore/QCoreApplication>
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/qpa/qwindowsysteminterface.h>
@ -61,8 +62,140 @@ public:
QWindowsDirect2DContext m_d2dContext;
};
class Direct2DVersion
{
private:
Direct2DVersion()
: partOne(0)
, partTwo(0)
, partThree(0)
, partFour(0)
{}
Direct2DVersion(int one, int two, int three, int four)
: partOne(one)
, partTwo(two)
, partThree(three)
, partFour(four)
{}
public:
// 6.2.9200.16765 corresponds to Direct2D 1.1 on Windows 7 SP1 with Platform Update
enum {
D2DMinVersionPart1 = 6,
D2DMinVersionPart2 = 2,
D2DMinVersionPart3 = 9200,
D2DMinVersionPart4 = 16765
};
static Direct2DVersion systemVersion() {
static const int bufSize = 512;
TCHAR filename[bufSize];
UINT i = GetSystemDirectory(filename, bufSize);
if (i > 0 && i < MAX_PATH) {
if (_tcscat_s(filename, MAX_PATH, __TEXT("\\d2d1.dll")) == 0) {
DWORD versionInfoSize = GetFileVersionInfoSize(filename, NULL);
if (versionInfoSize) {
QVector<BYTE> info(versionInfoSize);
if (GetFileVersionInfo(filename, NULL, versionInfoSize, info.data())) {
UINT size;
DWORD *fi;
if (VerQueryValue(info.constData(), __TEXT("\\"), (LPVOID *) &fi, &size) && size) {
VS_FIXEDFILEINFO *verInfo = (VS_FIXEDFILEINFO *) fi;
return Direct2DVersion(HIWORD(verInfo->dwFileVersionMS),
LOWORD(verInfo->dwFileVersionMS),
HIWORD(verInfo->dwFileVersionLS),
LOWORD(verInfo->dwFileVersionLS));
}
}
}
}
}
return Direct2DVersion();
}
static Direct2DVersion minimumVersion() {
return Direct2DVersion(D2DMinVersionPart1,
D2DMinVersionPart2,
D2DMinVersionPart3,
D2DMinVersionPart4);
}
bool isValid() const {
return partOne || partTwo || partThree || partFour;
}
bool operator<(const Direct2DVersion &other) {
int c = cmp(partOne, other.partOne);
if (c > 0)
return false;
if (c < 0)
return true;
c = cmp(partTwo, other.partTwo);
if (c > 0)
return false;
if (c < 0)
return true;
c = cmp(partThree, other.partThree);
if (c > 0)
return false;
if (c < 0)
return true;
c = cmp(partFour, other.partFour);
if (c > 0)
return false;
if (c < 0)
return true;
return false;
}
static Q_DECL_CONSTEXPR int cmp(int a, int b) {
return a - b;
}
int partOne, partTwo, partThree, partFour;
};
QWindowsDirect2DIntegration *QWindowsDirect2DIntegration::create(const QStringList &paramList)
{
Direct2DVersion systemVersion = Direct2DVersion::systemVersion();
if (systemVersion.isValid() && systemVersion < Direct2DVersion::minimumVersion()) {
QString msg = QCoreApplication::translate("QWindowsDirect2DIntegration",
"Qt cannot load the direct2d platform plugin because " \
"the Direct2D version on this system is too old. The " \
"minimum system requirement for this platform plugin " \
"is Windows 7 SP1 with Platform Update.\n\n" \
"The minimum Direct2D version required is %1.%2.%3.%4. " \
"The Direct2D version on this system is %5.%6.%7.%8.");
msg = msg.arg(Direct2DVersion::D2DMinVersionPart1)
.arg(Direct2DVersion::D2DMinVersionPart2)
.arg(Direct2DVersion::D2DMinVersionPart3)
.arg(Direct2DVersion::D2DMinVersionPart4)
.arg(systemVersion.partOne)
.arg(systemVersion.partTwo)
.arg(systemVersion.partThree)
.arg(systemVersion.partFour);
QString caption = QCoreApplication::translate("QWindowsDirect2DIntegration",
"Cannot load direct2d platform plugin");
MessageBoxW(NULL,
msg.toStdWString().c_str(),
caption.toStdWString().c_str(),
MB_OK | MB_ICONERROR);
return Q_NULLPTR;
}
QWindowsDirect2DIntegration *integration = new QWindowsDirect2DIntegration(paramList);
if (!integration->init()) {

View File

@ -58,7 +58,6 @@
#include <QtGui/private/qfontengine_p.h>
#include <QtGui/private/qstatictext_p.h>
#include <wrl.h>
using Microsoft::WRL::ComPtr;
QT_BEGIN_NAMESPACE
@ -346,6 +345,8 @@ public:
QPointF currentBrushOrigin;
QHash< QFont, ComPtr<IDWriteFontFace> > fontCache;
struct {
bool emulate;
QPen qpen;
@ -1291,44 +1292,6 @@ void QWindowsDirect2DPaintEngine::drawPixmap(const QRectF &r,
}
}
static ComPtr<IDWriteFontFace> fontFaceFromFontEngine(QFontEngine *fe)
{
ComPtr<IDWriteFontFace> fontFace;
switch (fe->type()) {
case QFontEngine::Win:
{
QWindowsFontEngine *wfe = static_cast<QWindowsFontEngine *>(fe);
QSharedPointer<QWindowsFontEngineData> wfed = wfe->fontEngineData();
HGDIOBJ oldfont = wfe->selectDesignFont();
HRESULT hr = QWindowsDirect2DContext::instance()->dwriteGdiInterop()->CreateFontFaceFromHdc(wfed->hdc, &fontFace);
DeleteObject(SelectObject(wfed->hdc, oldfont));
if (FAILED(hr))
qWarning("%s: Could not create DirectWrite fontface from HDC: %#x", __FUNCTION__, hr);
}
break;
#ifndef QT_NO_DIRECTWRITE
case QFontEngine::DirectWrite:
{
QWindowsFontEngineDirectWrite *wfedw = static_cast<QWindowsFontEngineDirectWrite *>(fe);
fontFace = wfedw->directWriteFontFace();
}
break;
#endif // QT_NO_DIRECTWRITE
default:
qWarning("%s: Unknown font engine!", __FUNCTION__);
break;
}
return fontFace;
}
void QWindowsDirect2DPaintEngine::drawStaticTextItem(QStaticTextItem *staticTextItem)
{
Q_D(QWindowsDirect2DPaintEngine);
@ -1340,24 +1303,22 @@ void QWindowsDirect2DPaintEngine::drawStaticTextItem(QStaticTextItem *staticText
ensurePen();
// If we can't support the current configuration with Direct2D, fall back to slow path
// Most common cases are perspective transform and gradient brush as pen
if ((state()->transform().isAffine() == false) || d->pen.emulate) {
if (emulationRequired(PenEmulation)) {
QPaintEngineEx::drawStaticTextItem(staticTextItem);
return;
}
ComPtr<IDWriteFontFace> fontFace = fontFaceFromFontEngine(staticTextItem->fontEngine());
ComPtr<IDWriteFontFace> fontFace = fontFaceFromFontEngine(staticTextItem->font, staticTextItem->fontEngine());
if (!fontFace) {
qWarning("%s: Could not find font - falling back to slow text rendering path.", __FUNCTION__);
QPaintEngineEx::drawStaticTextItem(staticTextItem);
return;
}
QVector<UINT16> glyphIndices(staticTextItem->numGlyphs);
QVector<FLOAT> glyphAdvances(staticTextItem->numGlyphs);
QVector<DWRITE_GLYPH_OFFSET> glyphOffsets(staticTextItem->numGlyphs);
QVarLengthArray<UINT16> glyphIndices(staticTextItem->numGlyphs);
QVarLengthArray<FLOAT> glyphAdvances(staticTextItem->numGlyphs);
QVarLengthArray<DWRITE_GLYPH_OFFSET> glyphOffsets(staticTextItem->numGlyphs);
// XXX Are we generating a lot of cache misses here?
for (int i = 0; i < staticTextItem->numGlyphs; i++) {
glyphIndices[i] = UINT16(staticTextItem->glyphs[i]); // Imperfect conversion here
@ -1390,24 +1351,22 @@ void QWindowsDirect2DPaintEngine::drawTextItem(const QPointF &p, const QTextItem
ensurePen();
// If we can't support the current configuration with Direct2D, fall back to slow path
// Most common cases are perspective transform and gradient brush as pen
if ((state()->transform().isAffine() == false) || d->pen.emulate) {
if (emulationRequired(PenEmulation)) {
QPaintEngine::drawTextItem(p, textItem);
return;
}
ComPtr<IDWriteFontFace> fontFace = fontFaceFromFontEngine(ti.fontEngine);
ComPtr<IDWriteFontFace> fontFace = fontFaceFromFontEngine(*ti.f, ti.fontEngine);
if (!fontFace) {
qWarning("%s: Could not find font - falling back to slow text rendering path.", __FUNCTION__);
QPaintEngine::drawTextItem(p, textItem);
return;
}
QVector<UINT16> glyphIndices(ti.glyphs.numGlyphs);
QVector<FLOAT> glyphAdvances(ti.glyphs.numGlyphs);
QVector<DWRITE_GLYPH_OFFSET> glyphOffsets(ti.glyphs.numGlyphs);
QVarLengthArray<UINT16> glyphIndices(ti.glyphs.numGlyphs);
QVarLengthArray<FLOAT> glyphAdvances(ti.glyphs.numGlyphs);
QVarLengthArray<DWRITE_GLYPH_OFFSET> glyphOffsets(ti.glyphs.numGlyphs);
// XXX Are we generating a lot of cache misses here?
for (int i = 0; i < ti.glyphs.numGlyphs; i++) {
glyphIndices[i] = UINT16(ti.glyphs.glyphs[i]); // Imperfect conversion here
glyphAdvances[i] = ti.glyphs.effectiveAdvance(i).toReal();
@ -1618,4 +1577,49 @@ void QWindowsDirect2DPaintEngine::adjustForAliasing(QPointF *point)
(*point) += adjustment;
}
Microsoft::WRL::ComPtr<IDWriteFontFace> QWindowsDirect2DPaintEngine::fontFaceFromFontEngine(const QFont &font, QFontEngine *fe)
{
Q_D(QWindowsDirect2DPaintEngine);
ComPtr<IDWriteFontFace> fontFace = d->fontCache.value(font);
if (fontFace)
return fontFace;
switch (fe->type()) {
case QFontEngine::Win:
{
QWindowsFontEngine *wfe = static_cast<QWindowsFontEngine *>(fe);
QSharedPointer<QWindowsFontEngineData> wfed = wfe->fontEngineData();
HGDIOBJ oldfont = wfe->selectDesignFont();
HRESULT hr = QWindowsDirect2DContext::instance()->dwriteGdiInterop()->CreateFontFaceFromHdc(wfed->hdc, &fontFace);
DeleteObject(SelectObject(wfed->hdc, oldfont));
if (FAILED(hr))
qWarning("%s: Could not create DirectWrite fontface from HDC: %#x", __FUNCTION__, hr);
}
break;
#ifndef QT_NO_DIRECTWRITE
case QFontEngine::DirectWrite:
{
QWindowsFontEngineDirectWrite *wfedw = static_cast<QWindowsFontEngineDirectWrite *>(fe);
fontFace = wfedw->directWriteFontFace();
}
break;
#endif // QT_NO_DIRECTWRITE
default:
qWarning("%s: Unknown font engine!", __FUNCTION__);
break;
}
if (fontFace)
d->fontCache.insert(font, fontFace);
return fontFace;
}
QT_END_NAMESPACE

View File

@ -47,6 +47,7 @@
#include <d2d1_1.h>
#include <dwrite_1.h>
#include <wrl.h>
QT_BEGIN_NAMESPACE
@ -114,6 +115,8 @@ private:
bool antiAliasingEnabled() const;
void adjustForAliasing(QRectF *rect);
void adjustForAliasing(QPointF *point);
Microsoft::WRL::ComPtr<IDWriteFontFace> fontFaceFromFontEngine(const QFont &font, QFontEngine *fe);
};
QT_END_NAMESPACE

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@ -56,12 +56,27 @@ class QWindowsDirect2DPlatformPixmapPrivate
{
public:
QWindowsDirect2DPlatformPixmapPrivate()
: bitmap(new QWindowsDirect2DBitmap)
, device(new QWindowsDirect2DPaintDevice(bitmap.data(), QInternal::Pixmap))
: owns_bitmap(true)
, bitmap(new QWindowsDirect2DBitmap)
, device(new QWindowsDirect2DPaintDevice(bitmap, QInternal::Pixmap))
, devicePixelRatio(1.0)
{}
QScopedPointer<QWindowsDirect2DBitmap> bitmap;
QWindowsDirect2DPlatformPixmapPrivate(QWindowsDirect2DBitmap *bitmap)
: owns_bitmap(false)
, bitmap(bitmap)
, device(new QWindowsDirect2DPaintDevice(bitmap, QInternal::Pixmap))
, devicePixelRatio(1.0)
{}
~QWindowsDirect2DPlatformPixmapPrivate()
{
if (owns_bitmap)
delete bitmap;
}
bool owns_bitmap;
QWindowsDirect2DBitmap *bitmap;
QScopedPointer<QWindowsDirect2DPaintDevice> device;
qreal devicePixelRatio;
};
@ -75,6 +90,19 @@ QWindowsDirect2DPlatformPixmap::QWindowsDirect2DPlatformPixmap(PixelType pixelTy
setSerialNumber(qt_d2dpixmap_serno++);
}
QWindowsDirect2DPlatformPixmap::QWindowsDirect2DPlatformPixmap(QPlatformPixmap::PixelType pixelType,
QWindowsDirect2DBitmap *bitmap)
: QPlatformPixmap(pixelType, Direct2DClass)
, d_ptr(new QWindowsDirect2DPlatformPixmapPrivate(bitmap))
{
setSerialNumber(qt_d2dpixmap_serno++);
is_null = false;
w = bitmap->size().width();
h = bitmap->size().height();
this->d = 32;
}
QWindowsDirect2DPlatformPixmap::~QWindowsDirect2DPlatformPixmap()
{
@ -173,7 +201,7 @@ void QWindowsDirect2DPlatformPixmap::setDevicePixelRatio(qreal scaleFactor)
QWindowsDirect2DBitmap *QWindowsDirect2DPlatformPixmap::bitmap() const
{
Q_D(const QWindowsDirect2DPlatformPixmap);
return d->bitmap.data();
return d->bitmap;
}
QT_END_NAMESPACE

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@ -55,6 +55,9 @@ class QWindowsDirect2DPlatformPixmap : public QPlatformPixmap
Q_DECLARE_PRIVATE(QWindowsDirect2DPlatformPixmap)
public:
QWindowsDirect2DPlatformPixmap(PixelType pixelType);
// We do NOT take ownership of the bitmap through this constructor!
QWindowsDirect2DPlatformPixmap(PixelType pixelType, QWindowsDirect2DBitmap *bitmap);
~QWindowsDirect2DPlatformPixmap();
virtual void resize(int width, int height);

View File

@ -43,6 +43,7 @@
#include "qwindowsdirect2dwindow.h"
#include "qwindowsdirect2ddevicecontext.h"
#include "qwindowsdirect2dhelpers.h"
#include "qwindowsdirect2dplatformpixmap.h"
#include <d3d11.h>
#include <d2d1_1.h>
@ -87,6 +88,13 @@ QWindowsDirect2DWindow::~QWindowsDirect2DWindow()
{
}
QPixmap *QWindowsDirect2DWindow::pixmap()
{
setupBitmap();
return m_pixmap.data();
}
void QWindowsDirect2DWindow::flush(QWindowsDirect2DBitmap *bitmap, const QRegion &region, const QPoint &offset)
{
DXGI_SWAP_CHAIN_DESC1 desc;
@ -102,32 +110,38 @@ void QWindowsDirect2DWindow::flush(QWindowsDirect2DBitmap *bitmap, const QRegion
if (!m_bitmap)
return;
m_bitmap->deviceContext()->begin();
if (bitmap != m_bitmap.data()) {
m_bitmap->deviceContext()->begin();
ID2D1DeviceContext *dc = m_bitmap->deviceContext()->get();
if (!m_needsFullFlush) {
QRegion clipped = region;
clipped &= QRect(0, 0, desc.Width, desc.Height);
ID2D1DeviceContext *dc = m_bitmap->deviceContext()->get();
if (!m_needsFullFlush) {
QRegion clipped = region;
clipped &= QRect(0, 0, desc.Width, desc.Height);
foreach (const QRect &rect, clipped.rects()) {
QRectF rectF(rect);
foreach (const QRect &rect, clipped.rects()) {
QRectF rectF(rect);
dc->DrawBitmap(bitmap->bitmap(),
to_d2d_rect_f(rectF),
1.0,
D2D1_INTERPOLATION_MODE_LINEAR,
to_d2d_rect_f(rectF.translated(offset.x(), offset.y())));
}
} else {
QRectF rectF(0, 0, desc.Width, desc.Height);
dc->DrawBitmap(bitmap->bitmap(),
to_d2d_rect_f(rectF),
1.0,
D2D1_INTERPOLATION_MODE_LINEAR,
to_d2d_rect_f(rectF.translated(offset.x(), offset.y())));
m_needsFullFlush = false;
}
} else {
QRectF rectF(0, 0, desc.Width, desc.Height);
dc->DrawBitmap(bitmap->bitmap(),
to_d2d_rect_f(rectF),
1.0,
D2D1_INTERPOLATION_MODE_LINEAR,
to_d2d_rect_f(rectF.translated(offset.x(), offset.y())));
m_needsFullFlush = false;
}
m_bitmap->deviceContext()->end();
m_bitmap->deviceContext()->end();
}
}
void QWindowsDirect2DWindow::present()
{
m_swapChain->Present(0, 0);
}
@ -136,6 +150,7 @@ void QWindowsDirect2DWindow::resizeSwapChain(const QSize &size)
if (!m_swapChain)
return;
m_pixmap.reset();
m_bitmap.reset();
m_deviceContext->SetTarget(Q_NULLPTR);
@ -149,6 +164,43 @@ void QWindowsDirect2DWindow::resizeSwapChain(const QSize &size)
m_needsFullFlush = true;
}
QSharedPointer<QWindowsDirect2DBitmap> QWindowsDirect2DWindow::copyBackBuffer() const
{
const QSharedPointer<QWindowsDirect2DBitmap> null_result;
if (!m_bitmap)
return null_result;
D2D1_PIXEL_FORMAT format = m_bitmap->bitmap()->GetPixelFormat();
D2D1_SIZE_U size = m_bitmap->bitmap()->GetPixelSize();
FLOAT dpiX, dpiY;
m_bitmap->bitmap()->GetDpi(&dpiX, &dpiY);
D2D1_BITMAP_PROPERTIES1 properties = {
format, // D2D1_PIXEL_FORMAT pixelFormat;
dpiX, // FLOAT dpiX;
dpiY, // FLOAT dpiY;
D2D1_BITMAP_OPTIONS_TARGET, // D2D1_BITMAP_OPTIONS bitmapOptions;
Q_NULLPTR // _Field_size_opt_(1) ID2D1ColorContext *colorContext;
};
ComPtr<ID2D1Bitmap1> copy;
HRESULT hr = m_deviceContext.Get()->CreateBitmap(size, NULL, 0, properties, &copy);
if (FAILED(hr)) {
qWarning("%s: Could not create staging bitmap: %#x", __FUNCTION__, hr);
return null_result;
}
hr = copy.Get()->CopyFromBitmap(NULL, m_bitmap->bitmap(), NULL);
if (FAILED(hr)) {
qWarning("%s: Could not copy from bitmap! %#x", __FUNCTION__, hr);
return null_result;
}
return QSharedPointer<QWindowsDirect2DBitmap>(new QWindowsDirect2DBitmap(copy.Get(), Q_NULLPTR));
}
void QWindowsDirect2DWindow::setupBitmap()
{
if (m_bitmap)
@ -175,6 +227,10 @@ void QWindowsDirect2DWindow::setupBitmap()
}
m_bitmap.reset(new QWindowsDirect2DBitmap(backBufferBitmap.Get(), m_deviceContext.Get()));
QWindowsDirect2DPlatformPixmap *pp = new QWindowsDirect2DPlatformPixmap(QPlatformPixmap::PixmapType,
m_bitmap.data());
m_pixmap.reset(new QPixmap(pp));
}
QT_END_NAMESPACE

View File

@ -56,16 +56,21 @@ public:
QWindowsDirect2DWindow(QWindow *window, const QWindowsWindowData &data);
~QWindowsDirect2DWindow();
QPixmap *pixmap();
void flush(QWindowsDirect2DBitmap *bitmap, const QRegion &region, const QPoint &offset);
void present();
void resizeSwapChain(const QSize &size);
QSharedPointer<QWindowsDirect2DBitmap> copyBackBuffer() const;
private:
void resizeSwapChain(const QSize &size);
void setupBitmap();
private:
Microsoft::WRL::ComPtr<IDXGISwapChain1> m_swapChain;
Microsoft::WRL::ComPtr<ID2D1DeviceContext> m_deviceContext;
QScopedPointer<QWindowsDirect2DBitmap> m_bitmap;
QScopedPointer<QPixmap> m_pixmap;
bool m_needsFullFlush;
};

View File

@ -150,6 +150,7 @@
break;
}
QWindowSystemInterface::handleApplicationStateChanged(state);
QWindowSystemInterface::flushWindowSystemEvents();
}
@end

View File

@ -88,6 +88,7 @@ public:
WId winId() const { return WId(m_view); };
private:
void applicationStateChanged(Qt::ApplicationState state);
void applyGeometry(const QRect &rect);
QUIView *m_view;

View File

@ -192,12 +192,25 @@
- (void)displayLayer:(CALayer *)layer
{
QSize bounds = fromCGRect(layer.bounds).toRect().size();
Q_UNUSED(layer);
Q_ASSERT(layer == self.layer);
Q_ASSERT(m_qioswindow->geometry().size() == bounds);
Q_ASSERT(self.hidden == !m_qioswindow->window()->isVisible());
[self sendUpdatedExposeEvent];
}
- (void)sendUpdatedExposeEvent
{
QRegion region;
if (m_qioswindow->isExposed()) {
QSize bounds = fromCGRect(self.layer.bounds).toRect().size();
Q_ASSERT(m_qioswindow->geometry().size() == bounds);
Q_ASSERT(self.hidden == !m_qioswindow->window()->isVisible());
region = QRect(QPoint(), bounds);
}
QRegion region = self.hidden ? QRegion() : QRect(QPoint(), bounds);
QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), region);
QWindowSystemInterface::flushWindowSystemEvents();
}
@ -279,19 +292,33 @@
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
if (!touches && m_activeTouches.isEmpty())
if (m_activeTouches.isEmpty())
return;
if (!touches) {
m_activeTouches.clear();
} else {
for (UITouch *touch in touches)
m_activeTouches.remove(touch);
// When four-finger swiping, we get a touchesCancelled callback
// which includes all four touch points. The swipe gesture is
// then active until all four touches have been released, and
// we start getting touchesBegan events again.
Q_ASSERT_X(m_activeTouches.isEmpty(), Q_FUNC_INFO,
"Subset of active touches cancelled by UIKit");
}
// When five-finger pinching, we also get a touchesCancelled
// callback with all five touch points, but the pinch gesture
// ends when the second to last finger is released from the
// screen. The last finger will not emit any more touch
// events, _but_, will contribute to starting another pinch
// gesture. That second pinch gesture will _not_ trigger a
// touchesCancelled event when starting, but as each finger
// is released, and we may get touchesMoved events for the
// remaining fingers. [event allTouches] also contains one
// less touch point than it should, so this behavior is
// likely a bug in the iOS system gesture recognizer, but we
// have to take it into account when maintaining the Qt state.
// We do this by assuming that there are no cases where a
// sub-set of the active touch events are intentionally cancelled.
if (touches && (static_cast<NSInteger>([touches count]) != m_activeTouches.count()))
qWarning("Subset of active touches cancelled by UIKit");
m_activeTouches.clear();
m_nextTouchId = 0;
NSTimeInterval timestamp = event ? event.timestamp : [[NSProcessInfo processInfo] systemUptime];
@ -334,6 +361,8 @@ QIOSWindow::QIOSWindow(QWindow *window)
, m_view([[QUIView alloc] initWithQIOSWindow:this])
, m_windowLevel(0)
{
connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QIOSWindow::applicationStateChanged);
setParent(QPlatformWindow::parent());
// Resolve default window geometry in case it was not set before creating the
@ -471,7 +500,8 @@ void QIOSWindow::applyGeometry(const QRect &rect)
bool QIOSWindow::isExposed() const
{
return window()->isVisible() && !window()->geometry().isEmpty();
return qApp->applicationState() > Qt::ApplicationHidden
&& window()->isVisible() && !window()->geometry().isEmpty();
}
void QIOSWindow::setWindowState(Qt::WindowState state)
@ -593,6 +623,12 @@ void QIOSWindow::handleContentOrientationChange(Qt::ScreenOrientation orientatio
[[UIApplication sharedApplication] setStatusBarOrientation:uiOrientation animated:NO];
}
void QIOSWindow::applicationStateChanged(Qt::ApplicationState)
{
if (window()->isExposed() != isExposed())
[m_view sendUpdatedExposeEvent];
}
qreal QIOSWindow::devicePixelRatio() const
{
return m_view.contentScaleFactor;

View File

@ -85,8 +85,7 @@ QKmsDevice::~QKmsDevice()
void QKmsDevice::createScreens()
{
drmModeRes *resources = 0;
resources = drmModeGetResources(m_fd);
drmModeRes *resources = drmModeGetResources(m_fd);
if (!resources)
qFatal("drmModeGetResources failed");
@ -95,7 +94,7 @@ void QKmsDevice::createScreens()
drmModeConnector *connector = 0;
connector = drmModeGetConnector(m_fd, resources->connectors[i]);
if (connector && connector->connection == DRM_MODE_CONNECTED) {
m_integration->addScreen(new QKmsScreen(this, connector->connector_id));
m_integration->addScreen(new QKmsScreen(this, resources, connector));
}
drmModeFreeConnector(connector);
}

View File

@ -63,18 +63,18 @@ static drmModeModeInfo builtin_1024x768 = {
"1024x768"
};
QKmsScreen::QKmsScreen(QKmsDevice *device, int connectorId)
QKmsScreen::QKmsScreen(QKmsDevice *device, const drmModeRes *resources, const drmModeConnector *connector)
: m_device(device),
m_current_bo(0),
m_next_bo(0),
m_connectorId(connectorId),
m_connectorId(connector->connector_id),
m_depth(32),
m_format(QImage::Format_Invalid),
m_eglWindowSurface(EGL_NO_SURFACE),
m_modeSet(false)
{
m_cursor = new QKmsCursor(this);
initializeScreenMode();
initializeScreenMode(resources, connector);
}
QKmsScreen::~QKmsScreen()
@ -114,14 +114,9 @@ QPlatformCursor *QKmsScreen::cursor() const
return m_cursor;
}
void QKmsScreen::initializeScreenMode()
void QKmsScreen::initializeScreenMode(const drmModeRes *resources, const drmModeConnector *connector)
{
//Determine optimal mode for screen
drmModeRes *resources = drmModeGetResources(m_device->fd());
if (!resources)
qFatal("drmModeGetResources failed");
drmModeConnector *connector = drmModeGetConnector(m_device->fd(), m_connectorId);
drmModeModeInfo *mode = 0;
for (int i = 0; i < connector->count_modes; ++i) {
if (connector->modes[i].type & DRM_MODE_TYPE_PREFERRED) {
@ -129,8 +124,12 @@ void QKmsScreen::initializeScreenMode()
break;
}
}
if (!mode)
mode = &builtin_1024x768;
if (!mode) {
if (connector->count_modes > 0)
mode = &connector->modes[0];
else
mode = &builtin_1024x768;
}
drmModeEncoder *encoder = drmModeGetEncoder(m_device->fd(), connector->encoders[0]);
if (encoder == 0)
@ -162,8 +161,6 @@ void QKmsScreen::initializeScreenMode()
qDebug() << "created gbm surface" << m_gbmSurface << m_mode.hdisplay << m_mode.vdisplay;
//Cleanup
drmModeFreeEncoder(encoder);
drmModeFreeConnector(connector);
drmModeFreeResources(resources);
}
QSurfaceFormat QKmsScreen::tweakFormat(const QSurfaceFormat &format)

View File

@ -68,7 +68,7 @@ class QKmsContext;
class QKmsScreen : public QPlatformScreen
{
public:
QKmsScreen(QKmsDevice *device, int connectorId);
QKmsScreen(QKmsDevice *device, const drmModeRes *resources, const drmModeConnector *connector);
~QKmsScreen();
QRect geometry() const;
@ -94,7 +94,7 @@ public:
private:
void performPageFlip();
void initializeScreenMode();
void initializeScreenMode(const drmModeRes *resources, const drmModeConnector *connector);
QKmsDevice *m_device;
gbm_bo *m_current_bo;

View File

@ -145,9 +145,8 @@ void QWindowsBackingStore::resize(const QSize &size, const QRegion &region)
<< " from: " << (m_image.isNull() ? QSize() : m_image->image().size());
}
#endif
QImage::Format format = QWindowsNativeImage::systemFormat();
if (format == QImage::Format_RGB32 && window()->format().hasAlpha())
format = QImage::Format_ARGB32_Premultiplied;
const QImage::Format format = window()->format().hasAlpha() ?
QImage::Format_ARGB32_Premultiplied : QWindowsNativeImage::systemFormat();
QWindowsNativeImage *oldwni = m_image.data();
QWindowsNativeImage *newwni = new QWindowsNativeImage(size.width(), size.height(), format);

View File

@ -169,6 +169,20 @@ bool QWindowsFontEngine::hasCMapTable() const
return GetFontData(hdc, MAKE_TAG('c', 'm', 'a', 'p'), 0, 0, 0) != GDI_ERROR;
}
bool QWindowsFontEngine::hasGlyfTable() const
{
HDC hdc = m_fontEngineData->hdc;
SelectObject(hdc, hfont);
return GetFontData(hdc, MAKE_TAG('g', 'l', 'y', 'f'), 0, 0, 0) != GDI_ERROR;
}
bool QWindowsFontEngine::hasEbdtTable() const
{
HDC hdc = m_fontEngineData->hdc;
SelectObject(hdc, hfont);
return GetFontData(hdc, MAKE_TAG('E', 'B', 'D', 'T'), 0, 0, 0) != GDI_ERROR;
}
void QWindowsFontEngine::getCMap()
{
ttf = (bool)(tm.tmPitchAndFamily & TMPF_TRUETYPE) || hasCMapTable();
@ -308,6 +322,8 @@ QWindowsFontEngine::QWindowsFontEngine(const QString &name,
userData.insert(QStringLiteral("hFont"), QVariant::fromValue(hfont));
userData.insert(QStringLiteral("trueType"), QVariant(bool(ttf)));
setUserData(userData);
hasUnreliableOutline = hasGlyfTable() && hasEbdtTable();
}
QWindowsFontEngine::~QWindowsFontEngine()
@ -662,6 +678,11 @@ void QWindowsFontEngine::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qre
}
#endif // Q_CC_MINGW
bool QWindowsFontEngine::hasUnreliableGlyphOutline() const
{
return hasUnreliableOutline;
}
qreal QWindowsFontEngine::minLeftBearing() const
{
if (lbearing == SHRT_MIN)

View File

@ -122,6 +122,8 @@ public:
virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
#endif
bool hasUnreliableGlyphOutline() const Q_DECL_OVERRIDE;
int getGlyphIndexes(const QChar *ch, int numChars, QGlyphLayout *glyphs) const;
void getCMap();
@ -136,6 +138,8 @@ private:
QImage::Format mask_format);
bool hasCFFTable() const;
bool hasCMapTable() const;
bool hasGlyfTable() const;
bool hasEbdtTable() const;
const QSharedPointer<QWindowsFontEngineData> m_fontEngineData;
@ -146,6 +150,7 @@ private:
uint stockFont : 1;
uint ttf : 1;
uint hasOutline : 1;
uint hasUnreliableOutline : 1;
uint cffTable : 1;
TEXTMETRIC tm;
int lw;

View File

@ -496,6 +496,7 @@ QWinRTScreen::QWinRTScreen(ICoreWindow *window)
// Set initial orientation
onOrientationChanged(0);
setOrientationUpdateMask(m_nativeOrientation);
m_displayProperties->add_OrientationChanged(Callback<IDisplayPropertiesEventHandler>(this, &QWinRTScreen::onOrientationChanged).Get(),
&m_tokens[QEvent::OrientationChange]);

View File

@ -419,7 +419,7 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const
return;
}
m_format = QSurfaceFormat();
m_format.setRenderableType(QOpenGLContext::openGLModuleType() == QOpenGLContext::DesktopGL
m_format.setRenderableType(QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL
? QSurfaceFormat::OpenGL : QSurfaceFormat::OpenGLES);
updateFormatFromContext(m_format);
if (vinfo)

View File

@ -3,9 +3,8 @@
# libxcb-fixes, libxcb-randr, libxcb-shm, libxcb-sync, libxcb-image,
# libxcb-keysyms, libxcb-icccm, libxcb-renderutil, libxcb-xkb
#
TEMPLATE = lib
TARGET = xcb-static
CONFIG += staticlib
CONFIG += static
load(qt_helper_lib)
XCB_DIR = ../../../../3rdparty/xcb

View File

@ -1,5 +1,5 @@
TEMPLATE = subdirs
mac: SUBDIRS += cocoa
osx: SUBDIRS += cocoa
win32: SUBDIRS += windows
unix:!mac:contains(QT_CONFIG, cups): SUBDIRS += cups

View File

@ -448,9 +448,10 @@ bool QSqlTableModel::selectRow(int row)
// Look for changed values. Primary key fields are customarily first
// and probably change less often than other fields, so start at the end.
for (int f = curValues.count() - 1; f >= 0; --f) {
if (curValues.value(f) != newValues.value(f))
if (curValues.value(f) != newValues.value(f)) {
needsAddingToCache = true;
break;
}
}
}
}

View File

@ -201,11 +201,17 @@ inline bool qCompare(QList<T> const &t1, QList<T> const &t2, const char *actual,
}
for (int i = 0; isOk && i < actualSize; ++i) {
if (!(t1.at(i) == t2.at(i))) {
char *val1 = toString(t1.at(i));
char *val2 = toString(t2.at(i));
qsnprintf(msg, sizeof(msg), "Compared lists differ at index %d.\n"
" Actual (%s): %s\n"
" Expected (%s): %s", i, actual, toString(t1.at(i)),
expected, toString(t2.at(i)));
" Expected (%s): %s", i, actual, val1 ? val1 : "<null>",
expected, val2 ? val2 : "<null>");
isOk = false;
delete [] val1;
delete [] val2;
}
}
return compare_helper(isOk, msg, 0, 0, actual, expected, file, line);

View File

@ -2863,8 +2863,6 @@ bool QTest::currentTestFailed()
void QTest::qSleep(int ms)
{
QTEST_ASSERT(ms > 0);
QElapsedTimer timer;
timer.start();
#if defined(Q_OS_WINRT)
WaitForSingleObjectEx(GetCurrentThread(), ms, true);
@ -2874,20 +2872,6 @@ void QTest::qSleep(int ms)
struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
nanosleep(&ts, NULL);
#endif
// Warn if the elapsed time was more than 50% longer or more than 10% shorter than the
// requested time.
qint64 requested = 1000000 * (qint64)ms;
qint64 diff = timer.nsecsElapsed() - requested;
#ifndef Q_OS_WIN
const qint64 factor = 2; // more than 50% longer
#else
const qint64 factor = 1; // Windows: 50% is quite common, warn about 100%
#endif
if (diff * factor > requested || diff * 10 < -requested) {
QTestLog::warn(qPrintable(
QString::fromLatin1("QTest::qSleep() should have taken %1ns, but actually took %2ns!")
.arg(requested).arg(diff + requested)), __FILE__, __LINE__);
}
}
/*! \internal

View File

@ -647,10 +647,6 @@ QAccessible::State QAccessibleLineEdit::state() const
if (l->hasSelectedText())
state.selected = true;
if (l->contextMenuPolicy() != Qt::NoContextMenu
&& l->contextMenuPolicy() != Qt::PreventContextMenu)
state.hasPopup = true;
return state;
}

View File

@ -2128,6 +2128,11 @@ QString QFileDialog::getOpenFileName(QWidget *parent,
return QString();
}
static inline QUrl dialogResultToUrl(const QString &file)
{
return file.isEmpty() ? QUrl() : QUrl::fromLocalFile(file);
}
/*!
This is a convenience static function that returns an existing file
selected by the user. If the user presses Cancel, it returns an
@ -2166,7 +2171,7 @@ QUrl QFileDialog::getOpenFileUrl(QWidget *parent,
Q_UNUSED(supportedSchemes);
// Falls back to local file
return QUrl::fromLocalFile(getOpenFileName(parent, caption, dir.toLocalFile(), filter, selectedFilter, options));
return dialogResultToUrl(getOpenFileName(parent, caption, dir.toLocalFile(), filter, selectedFilter, options));
}
/*!
@ -2424,7 +2429,7 @@ QUrl QFileDialog::getSaveFileUrl(QWidget *parent,
Q_UNUSED(supportedSchemes);
// Falls back to local file
return QUrl::fromLocalFile(getSaveFileName(parent, caption, dir.toLocalFile(), filter, selectedFilter, options));
return dialogResultToUrl(getSaveFileName(parent, caption, dir.toLocalFile(), filter, selectedFilter, options));
}
/*!
@ -2532,7 +2537,7 @@ QUrl QFileDialog::getExistingDirectoryUrl(QWidget *parent,
Q_UNUSED(supportedSchemes);
// Falls back to local file
return QUrl::fromLocalFile(getExistingDirectory(parent, caption, dir.toLocalFile(), options));
return dialogResultToUrl(getExistingDirectory(parent, caption, dir.toLocalFile(), options));
}
inline static QString _qt_get_directory(const QString &path)

View File

@ -1655,7 +1655,7 @@ void QGraphicsView::invalidateScene(const QRectF &rect, QGraphicsScene::SceneLay
/*!
\property QGraphicsView::interactive
\brief whether the view allowed scene interaction.
\brief whether the view allows scene interaction.
If enabled, this view is set to allow scene interaction. Otherwise, this
view will not allow interaction, and any mouse or key events are ignored

View File

@ -1631,7 +1631,7 @@ QWidget *QListWidget::itemWidget(QListWidgetItem *item) const
/*!
\since 4.1
Sets the \a widget to be displayed in the give \a item.
Sets the \a widget to be displayed in the given \a item.
This function should only be used to display static content in the place of
a list widget item. If you want to display custom dynamic content or

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@ -1421,15 +1421,8 @@ void QTreeViewPrivate::adjustViewOptionsForIndex(QStyleOptionViewItem *option, c
const int right = (spanning ? header->visualIndex(0) : header->count() - 1 );
calcLogicalIndices(&logicalIndices, &viewItemPosList, left, right);
int columnIndex = 0;
for (int visualIndex = 0; visualIndex < current.column(); ++visualIndex) {
int logicalIndex = header->logicalIndex(visualIndex);
if (!header->isSectionHidden(logicalIndex)) {
++columnIndex;
}
}
option->viewItemPosition = viewItemPosList.at(columnIndex);
const int visualIndex = logicalIndices.indexOf(current.column());
option->viewItemPosition = viewItemPosList.at(visualIndex);
}

View File

@ -147,7 +147,7 @@ void QOpenGLWidget::paintGL()
void QOpenGLWidget::updateGL()
{
Q_D(QOpenGLWidget);
if (d->uninitialized)
if (d->uninitialized || !d->surface())
return;
makeCurrent();

View File

@ -440,11 +440,13 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
if (!win)
win = w->nativeParentWidget()->windowHandle();
if (win && win->geometry().contains(event->globalPos())) {
// Use postEvent() to ensure the local QEventLoop terminates when called from QMenu::exec()
const QPoint localPos = win->mapFromGlobal(event->globalPos());
QMouseEvent e(QEvent::MouseButtonPress, localPos, localPos, event->globalPos(), event->button(), event->buttons(), event->modifiers());
QGuiApplicationPrivate::setMouseEventSource(&e, QGuiApplicationPrivate::mouseEventSource(event));
e.setTimestamp(event->timestamp());
QApplication::sendSpontaneousEvent(win, &e);
QMouseEvent *e = new QMouseEvent(QEvent::MouseButtonPress, localPos, localPos, event->globalPos(), event->button(), event->buttons(), event->modifiers());
e->spont = 1;
QGuiApplicationPrivate::setMouseEventSource(e, QGuiApplicationPrivate::mouseEventSource(event));
e->setTimestamp(event->timestamp());
QCoreApplication::postEvent(win, e);
}
}
}

View File

@ -1677,7 +1677,7 @@ QMacStylePrivate::QMacStylePrivate()
if (ptrHIShapeGetBounds == 0) {
QLibrary library(QLatin1String("/System/Library/Frameworks/Carbon.framework/Carbon"));
library.setLoadHints(QLibrary::ExportExternalSymbolsHint);
ptrHIShapeGetBounds = reinterpret_cast<PtrHIShapeGetBounds>(library.resolve("HIShapeGetBounds"));
ptrHIShapeGetBounds = reinterpret_cast<PtrHIShapeGetBounds>(library.resolve("HIShapeGetBounds"));
}
}
@ -5300,7 +5300,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)){
HIThemeButtonDrawInfo bdi;
d->initComboboxBdi(combo, &bdi, widget, d->getDrawState(opt->state));
if (!tds == kThemeStateInactive)
if (tds != kThemeStateInactive)
QMacStylePrivate::drawCombobox(qt_hirectForQRect(combo->rect), bdi, p);
else
d->drawColorlessButton(qt_hirectForQRect(combo->rect), &bdi, p, opt);

View File

@ -2606,6 +2606,9 @@ bool QMdiArea::eventFilter(QObject *object, QEvent *event)
return QAbstractScrollArea::eventFilter(object, event);
}
if (subWindow->mdiArea() != this)
return QAbstractScrollArea::eventFilter(object, event);
// QMdiSubWindow events:
switch (event->type()) {
case QEvent::Move:

View File

@ -384,7 +384,7 @@ void QMenuBarPrivate::setCurrentAction(QAction *action, bool popup, bool activat
QAction *previousAction = currentAction;
#endif
currentAction = action;
if (action) {
if (action && action->isEnabled()) {
activateAction(action, QAction::Hover);
if(popup)
popupAction(action, activateFirst);
@ -1038,7 +1038,7 @@ void QMenuBar::mousePressEvent(QMouseEvent *e)
d->mouseDown = true;
QAction *action = d->actionAt(e->pos());
if (!action || !d->isVisible(action)) {
if (!action || !d->isVisible(action) || !action->isEnabled()) {
d->setCurrentAction(0);
#ifndef QT_NO_WHATSTHIS
if (QWhatsThis::inWhatsThisMode())

View File

@ -438,7 +438,6 @@ void QWidgetTextControlPrivate::setContent(Qt::TextFormat format, const QString
QObject::connect(doc, SIGNAL(contentsChanged()), q, SLOT(_q_updateCurrentCharFormatAndSelection()));
QObject::connect(doc, SIGNAL(cursorPositionChanged(QTextCursor)), q, SLOT(_q_emitCursorPosChanged(QTextCursor)));
QObject::connect(doc, SIGNAL(contentsChange(int,int,int)), q, SLOT(_q_contentsChanged(int,int,int)));
QObject::connect(doc, SIGNAL(documentLayoutChanged()), q, SLOT(_q_documentLayoutChanged()));
// convenience signal forwards
@ -501,6 +500,8 @@ void QWidgetTextControlPrivate::setContent(Qt::TextFormat format, const QString
q->ensureCursorVisible();
emit q->cursorPositionChanged();
QObject::connect(doc, SIGNAL(contentsChange(int,int,int)), q, SLOT(_q_contentsChanged(int,int,int)), Qt::UniqueConnection);
}
void QWidgetTextControlPrivate::startDrag()
@ -646,7 +647,8 @@ void QWidgetTextControlPrivate::_q_contentsChanged(int from, int charsRemoved, i
{
Q_Q(QWidgetTextControl);
#ifndef QT_NO_ACCESSIBILITY
if (QAccessible::isActive()) {
if (QAccessible::isActive() && q->parent() && q->parent()->isWidgetType()) {
QTextCursor tmp(doc);
tmp.setPosition(from);
tmp.setPosition(from + charsAdded, QTextCursor::KeepAnchor);

View File

@ -192,6 +192,8 @@ private slots:
void QTBUG28998_linkColor();
void textCursorUsageWithinContentsChange();
private:
void backgroundImage_checkExpectedHtml(const QTextDocument &doc);
@ -3021,5 +3023,50 @@ void tst_QTextDocument::QTBUG28998_linkColor()
QCOMPARE(format.foreground(), pal.link());
}
class ContentsChangeHandler : public QObject
{
Q_OBJECT
public:
ContentsChangeHandler(QTextDocument *doc)
: verticalMovementX(-1)
, doc(doc)
{
connect(doc, SIGNAL(contentsChange(int,int,int)),
this, SLOT(saveModifiedText(int, int, int)));
}
private slots:
void saveModifiedText(int from, int /*charsRemoved*/, int charsAdded)
{
QTextCursor tmp(doc);
tmp.setPosition(from);
tmp.setPosition(from + charsAdded, QTextCursor::KeepAnchor);
text = tmp.selectedText();
verticalMovementX = tmp.verticalMovementX();
}
public:
QString text;
int verticalMovementX;
private:
QTextDocument *doc;
};
void tst_QTextDocument::textCursorUsageWithinContentsChange()
{
// force creation of layout
doc->documentLayout();
QTextCursor cursor(doc);
cursor.insertText("initial text");
ContentsChangeHandler handler(doc);
cursor.insertText("new text");
QCOMPARE(handler.text, QString("new text"));
QCOMPARE(handler.verticalMovementX, -1);
}
QTEST_MAIN(tst_QTextDocument)
#include "tst_qtextdocument.moc"

View File

@ -122,6 +122,7 @@ private slots:
void boundingRectForUnsetLineWidth();
void boundingRectForSetLineWidth();
void glyphLessItems();
void justifyTrailingSpaces();
// QTextLine stuff
void setNumColumnsWrapAtWordBoundaryOrAnywhere();
@ -1996,5 +1997,19 @@ void tst_QTextLayout::cursorInNonStopChars()
QVERIFY(line.cursorToX(2) == line.cursorToX(3));
}
void tst_QTextLayout::justifyTrailingSpaces()
{
QTextLayout layout(QStringLiteral(" t"), testFont);
layout.setTextOption(QTextOption(Qt::AlignJustify));
layout.beginLayout();
QTextLine line = layout.createLine();
line.setLineWidth(5);
layout.endLayout();
QVERIFY(qFuzzyIsNull(layout.lineAt(0).cursorToX(0)));
}
QTEST_MAIN(tst_QTextLayout)
#include "tst_qtextlayout.moc"

View File

@ -81,6 +81,7 @@ private slots:
void emptyConstructor();
void constructor_data();
void constructor();
void constructor_device();
void constructingGarbage();
void copyAndAssign_data();
void copyAndAssign();
@ -111,6 +112,8 @@ private slots:
void verify();
void extensions();
void threadSafeConstMethods();
void version_data();
void version();
// helper for verbose test failure messages
QString toString(const QList<QSslError>&);
@ -226,6 +229,47 @@ void tst_QSslCertificate::constructor()
QVERIFY(!certificate.isNull());
}
void tst_QSslCertificate::constructor_device()
{
if (!QSslSocket::supportsSsl())
return;
QFile f(testDataDir + "/verify-certs/test-ocsp-good-cert.pem");
bool ok = f.open(QIODevice::ReadOnly);
QVERIFY(ok);
QSslCertificate cert(&f);
QVERIFY(!cert.isNull());
f.close();
// Check opening a DER as a PEM fails
QFile f2(testDataDir + "/certificates/cert.der");
ok = f2.open(QIODevice::ReadOnly);
QVERIFY(ok);
QSslCertificate cert2(&f2);
QVERIFY(cert2.isNull());
f2.close();
// Check opening a DER as a DER works
QFile f3(testDataDir + "/certificates/cert.der");
ok = f3.open(QIODevice::ReadOnly);
QVERIFY(ok);
QSslCertificate cert3(&f3, QSsl::Der);
QVERIFY(!cert3.isNull());
f3.close();
// Check opening a PEM as a DER fails
QFile f4(testDataDir + "/verify-certs/test-ocsp-good-cert.pem");
ok = f4.open(QIODevice::ReadOnly);
QVERIFY(ok);
QSslCertificate cert4(&f4, QSsl::Der);
QVERIFY(cert4.isNull());
f4.close();
}
void tst_QSslCertificate::constructingGarbage()
{
if (!QSslSocket::supportsSsl())
@ -1158,6 +1202,33 @@ void tst_QSslCertificate::threadSafeConstMethods()
}
void tst_QSslCertificate::version_data()
{
QTest::addColumn<QSslCertificate>("certificate");
QTest::addColumn<QByteArray>("result");
QTest::newRow("null certificate") << QSslCertificate() << QByteArray();
QList<QSslCertificate> certs;
certs << QSslCertificate::fromPath(testDataDir + "/verify-certs/test-ocsp-good-cert.pem");
QTest::newRow("v3 certificate") << certs.first() << QByteArrayLiteral("3");
certs.clear();
certs << QSslCertificate::fromPath(testDataDir + "/certificates/cert.pem");
QTest::newRow("v1 certificate") << certs.first() << QByteArrayLiteral("1");
}
void tst_QSslCertificate::version()
{
if (!QSslSocket::supportsSsl())
return;
QFETCH(QSslCertificate, certificate);
QFETCH(QByteArray, result);
QCOMPARE(certificate.version(), result);
}
#endif // QT_NO_SSL
QTEST_MAIN(tst_QSslCertificate)

View File

@ -1935,7 +1935,7 @@ void tst_QAccessibility::lineEditTest()
QVERIFY(iface->state().movable);
QVERIFY(iface->state().focusable);
QVERIFY(iface->state().selectable);
QVERIFY(iface->state().hasPopup);
QVERIFY(!iface->state().hasPopup);
QCOMPARE(bool(iface->state().focused), le->hasFocus());
QString secret(QLatin1String("secret"));
@ -1963,7 +1963,7 @@ void tst_QAccessibility::lineEditTest()
QVERIFY(!(iface->state().movable));
QVERIFY(iface->state().focusable);
QVERIFY(iface->state().selectable);
QVERIFY(iface->state().hasPopup);
QVERIFY(!iface->state().hasPopup);
QCOMPARE(bool(iface->state().focused), le->hasFocus());
QLineEdit *le2 = new QLineEdit(toplevel);

View File

@ -50,7 +50,7 @@
#include "qdebug.h"
#ifdef Q_OS_LINUX
#include <pthread.h>
#include <sched.h>
#endif
const QString qtest(qTableName("qtest", __FILE__, QSqlDatabase()));
@ -159,7 +159,7 @@ public:
q.bindValue(2, 10);
QVERIFY_SQL(q, exec());
#ifdef Q_OS_LINUX
pthread_yield();
sched_yield();
#endif
}
}
@ -197,7 +197,7 @@ public:
q1.clear();
QVERIFY_SQL(q2, exec());
#ifdef Q_OS_LINUX
pthread_yield();
sched_yield();
#endif
}
}

View File

@ -171,6 +171,7 @@ private slots:
void tildeExpansion();
#endif // QT_BUILD_INTERNAL
#endif
void getFileUrl();
private:
QByteArray userSettings;
@ -1429,5 +1430,49 @@ void tst_QFiledialog::tildeExpansion()
#endif // QT_BUILD_INTERNAL
#endif
class DialogRejecter : public QObject
{
Q_OBJECT
public:
DialogRejecter()
{
QTimer *timer = new QTimer(this);
timer->setInterval(1000);
connect(timer, &QTimer::timeout, this, &DialogRejecter::rejectFileDialog);
timer->start();
}
public slots:
void rejectFileDialog()
{
if (QWidget *w = QApplication::activeModalWidget())
if (QDialog *d = qobject_cast<QDialog *>(w))
d->reject();
}
};
void tst_QFiledialog::getFileUrl()
{
// QTBUG-38672 , static functions should return empty Urls
const QFileDialog::Options options = QFileDialog::DontUseNativeDialog;
DialogRejecter dr;
QUrl url = QFileDialog::getOpenFileUrl(0, QStringLiteral("getOpenFileUrl"),
QUrl(), QString(), Q_NULLPTR, options);
QVERIFY(url.isEmpty());
QVERIFY(!url.isValid());
url = QFileDialog::getExistingDirectoryUrl(0, QStringLiteral("getExistingDirectoryUrl"),
QUrl(), options | QFileDialog::ShowDirsOnly);
QVERIFY(url.isEmpty());
QVERIFY(!url.isValid());
url = QFileDialog::getSaveFileUrl(0, QStringLiteral("getSaveFileUrl"),
QUrl(), QString(), Q_NULLPTR, options);
QVERIFY(url.isEmpty());
QVERIFY(!url.isValid());
}
QTEST_MAIN(tst_QFiledialog)
#include "tst_qfiledialog.moc"

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the test suite of the Qt Toolkit.
@ -261,6 +261,7 @@ private slots:
void taskQTBUG_18539_emitLayoutChanged();
void taskQTBUG_8176_emitOnExpandAll();
void taskQTBUG_34717_collapseAtBottom();
void taskQTBUG_37813_crash();
void testInitialFocus();
};
@ -4327,5 +4328,31 @@ void tst_QTreeView::quickExpandCollapse()
}
#endif
void tst_QTreeView::taskQTBUG_37813_crash()
{
// QTBUG_37813: Crash in visual / logical index mapping in QTreeViewPrivate::adjustViewOptionsForIndex()
// when hiding/moving columns. It is reproduceable with a QTreeWidget only.
#ifdef QT_BUILD_INTERNAL
QTreeWidget treeWidget;
treeWidget.setDragEnabled(true);
treeWidget.setColumnCount(2);
QList<QTreeWidgetItem *> items;
for (int r = 0; r < 2; ++r) {
QTreeWidgetItem *item = new QTreeWidgetItem();
for (int c = 0; c < treeWidget.columnCount(); ++c)
item->setText(c, QString::fromLatin1("Row %1 Column %2").arg(r).arg(c));
items.append(item);
}
treeWidget.addTopLevelItems(items);
treeWidget.setColumnHidden(0, true);
treeWidget.header()->moveSection(0, 1);
QItemSelection sel(treeWidget.model()->index(0, 0), treeWidget.model()->index(0, 1));
QRect rect;
QAbstractItemViewPrivate *av = static_cast<QAbstractItemViewPrivate*>(qt_widget_private(&treeWidget));
const QPixmap pixmap = av->renderToPixmap(sel.indexes(), &rect);
QVERIFY(pixmap.size().isValid());
#endif // QT_BUILD_INTERNAL
}
QTEST_MAIN(tst_QTreeView)
#include "tst_qtreeview.moc"

View File

@ -49,6 +49,12 @@
#include "../../../qtest-config.h"
static inline void centerOnScreen(QWidget *w)
{
const QPoint offset = QPoint(w->width() / 2, w->height() / 2);
w->move(QGuiApplication::primaryScreen()->availableGeometry().center() - offset);
}
class tst_QStyleSheetStyle : public QObject
{
Q_OBJECT
@ -142,6 +148,8 @@ tst_QStyleSheetStyle::~tst_QStyleSheetStyle()
void tst_QStyleSheetStyle::numinstances()
{
QWidget w;
w.resize(200, 200);
centerOnScreen(&w);
QCommonStyle *style = new QCommonStyle;
style->setParent(&w);
QWidget c(&w);
@ -531,7 +539,14 @@ void tst_QStyleSheetStyle::dynamicProperty()
qApp->setStyleSheet(QString());
QString appStyle = qApp->style()->metaObject()->className();
QPushButton pb1, pb2;
QPushButton pb1(QStringLiteral("dynamicProperty_pb1"));
pb1.setMinimumWidth(160);
pb1.move(QGuiApplication::primaryScreen()->availableGeometry().topLeft() + QPoint(20, 100));
QPushButton pb2(QStringLiteral("dynamicProperty_pb2"));
pb2.setMinimumWidth(160);
pb2.move(QGuiApplication::primaryScreen()->availableGeometry().topLeft() + QPoint(20, 200));
pb1.setProperty("type", "critical");
qApp->setStyleSheet("*[class~=\"QPushButton\"] { color: red; } *[type=\"critical\"] { background: white; }");
QVERIFY(COLOR(pb1) == Qt::red);
@ -675,6 +690,8 @@ void tst_QStyleSheetStyle::onWidgetDestroyed()
void tst_QStyleSheetStyle::fontPrecedence()
{
QLineEdit edit;
edit.setMinimumWidth(200);
centerOnScreen(&edit);
edit.show();
QFont font;
QVERIFY(FONTSIZE(edit) != 22); // Sanity check to make sure this test makes sense.
@ -737,8 +754,9 @@ void tst_QStyleSheetStyle::focusColors()
// ten pixels of the right color requires quite a many characters, as the
// majority of the pixels will have slightly different colors due to the
// anti-aliasing effect.
#if !defined(Q_OS_WIN32) && !defined(Q_OS_MAC) && !(defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(Q_CC_INTEL))
QSKIP("This is a fragile test which fails on many esoteric platforms because of focus problems. "
#if !defined(Q_OS_WIN32) && !(defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(Q_CC_INTEL))
QSKIP("This is a fragile test which fails on many esoteric platforms because of focus problems"
" (for example, QTBUG-33959)."
"That doesn't mean that the feature doesn't work in practice.");
#endif
QList<QWidget *> widgets;
@ -768,6 +786,7 @@ void tst_QStyleSheetStyle::focusColors()
layout->addWidget(widget);
frame.setLayout(layout);
centerOnScreen(&frame);
frame.show();
QApplication::setActiveWindow(&frame);
QVERIFY(QTest::qWaitForWindowActive(&frame));
@ -795,6 +814,9 @@ void tst_QStyleSheetStyle::focusColors()
#ifndef QTEST_NO_CURSOR
void tst_QStyleSheetStyle::hoverColors()
{
#ifdef Q_OS_OSX
QSKIP("This test is fragile on Mac, most likely due to QTBUG-33959.");
#endif
QList<QWidget *> widgets;
widgets << new QPushButton("TESTING TESTING");
widgets << new QLineEdit("TESTING TESTING");
@ -822,31 +844,22 @@ void tst_QStyleSheetStyle::hoverColors()
layout->addWidget(widget);
frame.setLayout(layout);
centerOnScreen(&frame);
frame.show();
QApplication::setActiveWindow(&frame);
QVERIFY(QTest::qWaitForWindowActive(&frame));
//move the mouse inside the widget, it should be colored
QTest::mouseMove ( widget, QPoint(6,6));
QTest::qWait(60);
#ifdef Q_OS_MAC
QEXPECT_FAIL("", "Numerous failures related to Qt::WA_UnderMouse, see QTBUGT-23685", Continue);
#endif
QVERIFY(widget->testAttribute(Qt::WA_UnderMouse));
QTRY_VERIFY(widget->testAttribute(Qt::WA_UnderMouse));
QImage image(frame.width(), frame.height(), QImage::Format_ARGB32);
frame.render(&image);
#ifdef Q_OS_MAC
QEXPECT_FAIL("", "Numerous failures related to Qt::WA_UnderMouse, see QTBUGT-23685", Continue);
#endif
QVERIFY2(testForColors(image, QColor(0xe8, 0xff, 0x66)),
(QString::fromLatin1(widget->metaObject()->className())
+ " did not contain background color #e8ff66").toLocal8Bit().constData());
#ifdef Q_OS_MAC
QEXPECT_FAIL("", "Numerous failures related to Qt::WA_UnderMouse, see QTBUGT-23685", Continue);
#endif
QVERIFY2(testForColors(image, QColor(0xff, 0x00, 0x84)),
(QString::fromLatin1(widget->metaObject()->className())
+ " did not contain text color #ff0084").toLocal8Bit().constData());
@ -866,9 +879,7 @@ void tst_QStyleSheetStyle::hoverColors()
//move the mouse again inside the widget, it should be colored
QTest::mouseMove (widget, QPoint(5,5));
QTest::qWait(60);
QVERIFY(widget->testAttribute(Qt::WA_UnderMouse));
QTRY_VERIFY(widget->testAttribute(Qt::WA_UnderMouse));
frame.render(&image);
@ -904,35 +915,47 @@ public:
void tst_QStyleSheetStyle::background()
{
const int number = 4;
QWidget* widgets[number];
typedef QSharedPointer<QWidget> WidgetPtr;
const QString styleSheet = QStringLiteral("* { background-color: #e8ff66; }");
QVector<WidgetPtr> widgets;
const QPoint topLeft = QGuiApplication::primaryScreen()->availableGeometry().topLeft();
// Testing inheritance styling of QDialog.
widgets[0] = new SingleInheritanceDialog;
widgets[0]->setStyleSheet("* { background-color: #e8ff66; }");
widgets[1] = new DoubleInheritanceDialog;
widgets[1]->setStyleSheet("* { background-color: #e8ff66; }");
WidgetPtr toplevel(new SingleInheritanceDialog);
toplevel->resize(200, 200);
toplevel->move(topLeft + QPoint(20, 20));
toplevel->setStyleSheet(styleSheet);
widgets.append(toplevel);
toplevel = WidgetPtr(new DoubleInheritanceDialog);
toplevel->resize(200, 200);
toplevel->move(topLeft + QPoint(20, 320));
toplevel->setStyleSheet(styleSheet);
widgets.append(toplevel);
// Testing gradients in QComboBox.
QLayout* layout;
QComboBox* cb;
// First color
widgets[2] = new QDialog;
layout = new QGridLayout;
cb = new QComboBox;
toplevel = WidgetPtr(new QDialog);
toplevel->move(topLeft + QPoint(320, 20));
QGridLayout *layout = new QGridLayout(toplevel.data());
QComboBox* cb = new QComboBox;
cb->setMinimumWidth(160);
cb->setStyleSheet("* { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop:0 #e8ff66, stop:1 #000000); }");
layout->addWidget(cb);
widgets[2]->setLayout(layout);
layout->addWidget(cb, 0, 0);
widgets.append(toplevel);
// Second color
widgets[3] = new QDialog;
layout = new QGridLayout;
toplevel = WidgetPtr(new QDialog);
toplevel->move(topLeft + QPoint(320, 320));
layout = new QGridLayout(toplevel.data());
cb = new QComboBox;
cb->setMinimumWidth(160);
cb->setStyleSheet("* { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop:0 #e8ff66, stop:1 #000000); }");
layout->addWidget(cb);
widgets[3]->setLayout(layout);
for (int c = 0; c < number; ++c) {
QWidget* widget = widgets[c];
layout->addWidget(cb, 0, 0);
widgets.append(toplevel);
for (int c = 0; c < widgets.size(); ++c) {
QWidget *widget = widgets.at(c).data();
widget->setWindowTitle(QStringLiteral("background ") + QString::number(c));
widget->show();
QVERIFY(QTest::qWaitForWindowExposed(widget));
@ -941,12 +964,15 @@ void tst_QStyleSheetStyle::background()
if (image.depth() < 24)
QSKIP("Test doesn't support color depth < 24");
if (c == 2 && !QApplication::style()->objectName().compare(QLatin1String("fusion"), Qt::CaseInsensitive))
QEXPECT_FAIL("", "QTBUG-21468", Abort);
QVERIFY2(testForColors(image, QColor(0xe8, 0xff, 0x66)),
(QString::fromLatin1(widget->metaObject()->className())
(QString::number(c) + QLatin1Char(' ') + QString::fromLatin1(widget->metaObject()->className())
+ " did not contain background image with color #e8ff66")
.toLocal8Bit().constData());
delete widget;
widget->hide();
}
}
@ -956,6 +982,7 @@ void tst_QStyleSheetStyle::tabAlignement()
QTabWidget tabWidget(&topLevel);
tabWidget.addTab(new QLabel("tab1"),"tab1");
tabWidget.resize(QSize(400,400));
centerOnScreen(&topLevel);
topLevel.show();
QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
QTabBar *bar = tabWidget.findChild<QTabBar*>();
@ -1023,6 +1050,7 @@ void tst_QStyleSheetStyle::minmaxSizes()
tabWidget.setStyleSheet("QTabBar::tab { min-width:100px; max-width:130px; }");
centerOnScreen(&tabWidget);
tabWidget.show();
QTest::qWait(50);
//i allow 4px additional border from the native style (hence the -2, <=2)
@ -1050,6 +1078,7 @@ void tst_QStyleSheetStyle::task206238_twice()
tw->addTab(new QLabel("foo"), "test");
w.setCentralWidget(tw);
w.setStyleSheet("background: red;");
centerOnScreen(&w);
w.show();
QTest::qWait(20);
QCOMPARE(BACKGROUND(w) , QColor("red"));
@ -1219,6 +1248,8 @@ void tst_QStyleSheetStyle::proxyStyle()
QString styleSheet("QPushButton {background-color: red; }");
QWidget *w = new QWidget;
w->setMinimumWidth(160);
centerOnScreen(w);
QVBoxLayout *layout = new QVBoxLayout(w);
QPushButton *pb1 = new QPushButton(qApp->style()->objectName(), w);
@ -1294,6 +1325,7 @@ void tst_QStyleSheetStyle::emptyStyleSheet()
layout.addWidget(new QDateEdit(&w));
layout.addWidget(new QGroupBox("some text", &w));
centerOnScreen(&w);
w.show();
QVERIFY(QTest::qWaitForWindowExposed(&w));
//workaround the fact that the label sizehint is one pixel different the first time.
@ -1315,13 +1347,30 @@ void tst_QStyleSheetStyle::emptyStyleSheet()
img2.save("emptyStyleSheet_img2.png");
}
QEXPECT_FAIL("", "QTBUG-21468", Abort);
QCOMPARE(img1,img2);
}
class ApplicationStyleSetter
{
public:
explicit inline ApplicationStyleSetter(QStyle *s) : m_oldStyleName(QApplication::style()->objectName())
{ QApplication::setStyle(s); }
inline ~ApplicationStyleSetter()
{ QApplication::setStyle(QStyleFactory::create(m_oldStyleName)); }
private:
const QString m_oldStyleName;
};
void tst_QStyleSheetStyle::toolTip()
{
qApp->setStyleSheet(QString());
QWidget w;
// Use "Fusion" to prevent the Vista style from clobbering the tooltip palette in polish().
QStyle *fusionStyle = QStyleFactory::create(QLatin1String("Fusion"));
QVERIFY(fusionStyle);
ApplicationStyleSetter as(fusionStyle);
QHBoxLayout layout(&w);
w.setLayout(&layout);
@ -1349,11 +1398,12 @@ void tst_QStyleSheetStyle::toolTip()
wid4->setToolTip("this is wid4");
wid4->setObjectName("wid4");
centerOnScreen(&w);
w.show();
qApp->setActiveWindow(&w);
QVERIFY(QTest::qWaitForWindowActive(&w));
QColor normalToolTip = qApp->palette().toolTipBase().color();
const QColor normalToolTip = QToolTip::palette().color(QPalette::Inactive, QPalette::ToolTipBase);
QList<QWidget *> widgets;
QList<QColor> colors;
@ -1372,12 +1422,13 @@ void tst_QStyleSheetStyle::toolTip()
QWidget *tooltip = 0;
foreach (QWidget *widget, QApplication::topLevelWidgets()) {
if (widget->inherits("QTipLabel") && widget->isVisible()) {
if (widget->inherits("QTipLabel")) {
tooltip = widget;
break;
}
}
QVERIFY(tooltip);
QTRY_VERIFY(tooltip->isVisible()); // Wait until Roll-Effect is finished (Windows Vista)
QCOMPARE(tooltip->palette().color(tooltip->backgroundRole()), col);
}
@ -1394,6 +1445,8 @@ void tst_QStyleSheetStyle::embeddedFonts()
{
//task 235622 and 210551
QSpinBox spin;
spin.setMinimumWidth(160);
spin.move(QGuiApplication::primaryScreen()->availableGeometry().topLeft() + QPoint(20, 20));
spin.show();
spin.setStyleSheet("QSpinBox { font-size: 32px; }");
QTest::qWait(20);
@ -1411,6 +1464,8 @@ void tst_QStyleSheetStyle::embeddedFonts()
//task 242556
QComboBox box;
box.setMinimumWidth(160);
box.move(QGuiApplication::primaryScreen()->availableGeometry().topLeft() + QPoint(20, 120));
box.setEditable(true);
box.addItems(QStringList() << "First" << "Second" << "Third");
box.setStyleSheet("QComboBox { font-size: 32px; }");
@ -1483,6 +1538,7 @@ void tst_QStyleSheetStyle::complexWidgetFocus()
layout->addWidget(widget);
frame.setLayout(layout);
centerOnScreen(&frame);
frame.show();
QApplication::setActiveWindow(&frame);
QVERIFY(QTest::qWaitForWindowActive(&frame));
@ -1507,6 +1563,7 @@ void tst_QStyleSheetStyle::task188195_baseBackground()
{
QTreeView tree;
tree.setStyleSheet( "QTreeView:disabled { background-color:#ab1251; }" );
tree.move(QGuiApplication::primaryScreen()->availableGeometry().topLeft() + QPoint(20, 100));
tree.show();
QTest::qWait(20);
QImage image(tree.width(), tree.height(), QImage::Format_ARGB32);
@ -1527,6 +1584,7 @@ void tst_QStyleSheetStyle::task188195_baseBackground()
QTableWidget table(12, 12);
table.setItem(0, 0, new QTableWidgetItem());
table.setStyleSheet( "QTableView {background-color: #ff0000}" );
table.move(QGuiApplication::primaryScreen()->availableGeometry().topLeft() + QPoint(300, 100));
table.show();
QTest::qWait(20);
image = QImage(table.width(), table.height(), QImage::Format_ARGB32);
@ -1560,6 +1618,7 @@ void tst_QStyleSheetStyle::task232085_spinBoxLineEditBg()
layout->addWidget(spinbox);
frame.setLayout(layout);
centerOnScreen(&frame);
frame.show();
QApplication::setActiveWindow(&frame);
spinbox->setFocus();
@ -1619,6 +1678,7 @@ void tst_QStyleSheetStyle::QTBUG11658_cachecrash()
Widget(QWidget *parent = 0)
: QWidget(parent)
{
setMinimumWidth(160);
QVBoxLayout* pLayout = new QVBoxLayout(this);
QCheckBox* pCheckBox = new QCheckBox(this);
pLayout->addWidget(pCheckBox);
@ -1633,6 +1693,7 @@ void tst_QStyleSheetStyle::QTBUG11658_cachecrash()
Widget *w = new Widget();
delete w;
w = new Widget();
centerOnScreen(w);
w->show();
QVERIFY(QTest::qWaitForWindowExposed(w));
@ -1653,6 +1714,8 @@ void tst_QStyleSheetStyle::QTBUG15910_crashNullWidget()
}
} w;
w.setStyleSheet("* { background-color: white; color:black; border 3px solid yellow }");
w.setMinimumWidth(160);
centerOnScreen(&w);
w.show();
QVERIFY(QTest::qWaitForWindowExposed(&w));
}
@ -1675,6 +1738,7 @@ void tst_QStyleSheetStyle::QTBUG36933_brokenPseudoClassLookup()
// parsing of this stylesheet must not crash, and it must be correctly applied
widget.setStyleSheet(QStringLiteral("QHeaderView::section:vertical { background-color: #FF0000 }"));
centerOnScreen(&widget);
widget.show();
QVERIFY(QTest::qWaitForWindowExposed(&widget));
@ -1685,6 +1749,8 @@ void tst_QStyleSheetStyle::QTBUG36933_brokenPseudoClassLookup()
QHeaderView *verticalHeader = widget.verticalHeader();
QImage image(verticalHeader->size(), QImage::Format_ARGB32);
verticalHeader->render(&image);
if (!QApplication::style()->objectName().compare(QLatin1String("fusion"), Qt::CaseInsensitive))
QEXPECT_FAIL("", "QTBUG-21468", Abort);
QVERIFY(testForColors(image, QColor(0xFF, 0x00, 0x00)));
}

View File

@ -12,5 +12,5 @@ SUBDIRS=\
!mac:SUBDIRS -= \
qmacstyle \
!contains( styles, motif ):SUBDIRS -= \
ios|android|qnx|*wince*:SUBDIRS -= \
qstylesheetstyle \

View File

@ -60,26 +60,26 @@ class XmlServer : public QThread
{
Q_OBJECT
public:
XmlServer();
XmlServer(QObject *parent = 0) : QThread(parent), quit_soon(false), listening(false) {}
bool quit_soon;
bool listening;
protected:
virtual void run();
};
XmlServer::XmlServer()
{
quit_soon = false;
}
#define CHUNK_SIZE 1
#define CHUNK_SIZE 2048
void XmlServer::run()
{
QTcpServer srv;
if (!srv.listen(QHostAddress::Any, TEST_PORT))
listening = srv.listen(QHostAddress::Any, TEST_PORT);
if (!listening) {
qWarning() << "Failed to listen on" << TEST_PORT << srv.errorString();
return;
}
for (;;) {
srv.waitForNewConnection(100);
@ -168,12 +168,9 @@ class tst_QXmlSimpleReader : public QObject
QString prefix;
};
tst_QXmlSimpleReader::tst_QXmlSimpleReader()
tst_QXmlSimpleReader::tst_QXmlSimpleReader() : server(new XmlServer(this))
{
server = new XmlServer();
server->setParent(this);
server->start();
QTest::qSleep(1000);
}
tst_QXmlSimpleReader::~tst_QXmlSimpleReader()
@ -568,16 +565,13 @@ void tst_QXmlSimpleReader::inputFromSocket()
{
QFETCH(QString, file_name);
QTRY_VERIFY(server->listening);
QTcpSocket sock;
sock.connectToHost(QHostAddress::LocalHost, TEST_PORT);
const bool connectionSuccess = sock.waitForConnected();
if(!connectionSuccess) {
QTextStream out(stderr);
out << "QTcpSocket::errorString()" << sock.errorString();
}
QVERIFY(connectionSuccess);
QVERIFY2(sock.waitForConnected(),
qPrintable(QStringLiteral("Cannot connect on port ") + QString::number(TEST_PORT)
+ QStringLiteral(": ") + sock.errorString()));
sock.write(file_name.toLocal8Bit() + "\n");
QVERIFY(sock.waitForBytesWritten());