From ba7f76dea029bc56288ecb46925f5104c6915a71 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 26 Jan 2016 10:49:31 +0100 Subject: [PATCH 01/62] winrt: Add support for offscreen surfaces Previously offscreen surfaces were only needed to properly shutdown Qt Quick applications and the scene graph to have something to potentially render into but not show on the screen. However, Canvas3D requires a fully functional surface, preferably offscreen. Hence we use the QEGLPbuffer provided by eglconvenience in platformsupport. Task-number: QTBUG-50576 Change-Id: I1a32820bb2f2c6823be4e96dd92cf7965566f2c3 Reviewed-by: Miikka Heikkinen Reviewed-by: Andrew Knight --- .../platforms/winrt/qwinrteglcontext.cpp | 21 ++++++++++---- .../platforms/winrt/qwinrteglcontext.h | 2 ++ .../platforms/winrt/qwinrtintegration.cpp | 28 ++++++++++++++----- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.cpp b/src/plugins/platforms/winrt/qwinrteglcontext.cpp index bc77df566e4..882a7a69131 100644 --- a/src/plugins/platforms/winrt/qwinrteglcontext.cpp +++ b/src/plugins/platforms/winrt/qwinrteglcontext.cpp @@ -49,6 +49,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -148,14 +149,17 @@ bool QWinRTEGLContext::makeCurrent(QPlatformSurface *windowSurface) Q_D(QWinRTEGLContext); Q_ASSERT(windowSurface->surface()->supportsOpenGL()); - if (windowSurface->surface()->surfaceClass() == QSurface::Offscreen) - return false; + EGLSurface surface; + if (windowSurface->surface()->surfaceClass() == QSurface::Window) { + QWinRTWindow *window = static_cast(windowSurface); + if (window->eglSurface() == EGL_NO_SURFACE) + window->createEglSurface(g->eglDisplay, d->eglConfig); - QWinRTWindow *window = static_cast(windowSurface); - if (window->eglSurface() == EGL_NO_SURFACE) - window->createEglSurface(g->eglDisplay, d->eglConfig); + surface = window->eglSurface(); + } else { // Offscreen + surface = static_cast(windowSurface)->pbuffer(); + } - EGLSurface surface = window->eglSurface(); if (surface == EGL_NO_SURFACE) return false; @@ -346,4 +350,9 @@ QFunctionPointer QWinRTEGLContext::getProcAddress(const QByteArray &procName) return eglGetProcAddress(procName.constData()); } +EGLDisplay QWinRTEGLContext::display() +{ + return g->eglDisplay; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.h b/src/plugins/platforms/winrt/qwinrteglcontext.h index 31a2124b034..49b289cd79d 100644 --- a/src/plugins/platforms/winrt/qwinrteglcontext.h +++ b/src/plugins/platforms/winrt/qwinrteglcontext.h @@ -38,6 +38,7 @@ #define QWINDOWSEGLCONTEXT_H #include +#include QT_BEGIN_NAMESPACE @@ -57,6 +58,7 @@ public: QSurfaceFormat format() const Q_DECL_OVERRIDE; QFunctionPointer getProcAddress(const QByteArray &procName) Q_DECL_OVERRIDE; + static EGLDisplay display(); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QWinRTEGLContext) diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index 2281bf56ccd..9dac667ce54 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -45,12 +45,17 @@ #include "qwinrtfontdatabase.h" #include "qwinrttheme.h" -#include +#include #include -#include +#include +#include +#include +#include #include +#include + #include #include #include @@ -385,11 +390,20 @@ HRESULT QWinRTIntegration::onResume(IInspectable *, IInspectable *) QPlatformOffscreenSurface *QWinRTIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const { - // This is only used for shutdown of applications. - // In case we do not return an empty surface the scenegraph will try - // to create a new native window during application exit causing crashes - // or assertions. - return new QPlatformOffscreenSurface(surface); + QEGLPbuffer *pbuffer = nullptr; + HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([&pbuffer, surface]() { + pbuffer = new QEGLPbuffer(QWinRTEGLContext::display(), surface->requestedFormat(), surface); + return S_OK; + }); + if (hr == UI_E_WINDOW_CLOSED) { + // This is only used for shutdown of applications. + // In case we do not return an empty surface the scenegraph will try + // to create a new native window during application exit causing crashes + // or assertions. + return new QPlatformOffscreenSurface(surface); + } + + return pbuffer; } From a67a905190b85b53c30c9cb800b5e282d9364179 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 26 Jan 2016 14:45:46 +0100 Subject: [PATCH 02/62] Fix artihmetic exception when using non-scalable fonts For non-scalable fonts, the units_per_EM in FreeType is documented to be undefined and will default to 0, which means that any division by it will cause an exception. The emSquareSize() function already checks if the font is scalable and returns y_ppem if not, so lets use it instead in all locations where we're not already sure the font is scalable. [ChangeLog][Text][Freetype] Fixed a divide-by-zero exception when accessing bitmap fonts. Change-Id: I8839d4c83047fb3f6bb4d69af0258e94a258a4d9 Task-number: QTBUG-45963 Reviewed-by: Konstantin Ritt --- src/gui/text/qfontengine_ft.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 4dd2ee35b13..de5bec6f937 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -1255,7 +1255,7 @@ QFixed QFontEngineFT::xHeight() const TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2); if (os2 && os2->sxHeight) { lockFace(); - QFixed answer = QFixed(os2->sxHeight*freetype->face->size->metrics.y_ppem)/freetype->face->units_per_EM; + QFixed answer = QFixed(os2->sxHeight * freetype->face->size->metrics.y_ppem) / emSquareSize(); unlockFace(); return answer; } @@ -1267,7 +1267,7 @@ QFixed QFontEngineFT::averageCharWidth() const TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2); if (os2 && os2->xAvgCharWidth) { lockFace(); - QFixed answer = QFixed(os2->xAvgCharWidth*freetype->face->size->metrics.x_ppem)/freetype->face->units_per_EM; + QFixed answer = QFixed(os2->xAvgCharWidth * freetype->face->size->metrics.x_ppem) / emSquareSize(); unlockFace(); return answer; } @@ -1295,7 +1295,7 @@ void QFontEngineFT::doKerning(QGlyphLayout *g, QFontEngine::ShaperFlags flags) c kerning_pairs_loaded = true; lockFace(); if (freetype->face->size->metrics.x_ppem != 0) { - QFixed scalingFactor(freetype->face->units_per_EM/freetype->face->size->metrics.x_ppem); + QFixed scalingFactor = emSquareSize() / QFixed(freetype->face->size->metrics.x_ppem); unlockFace(); const_cast(this)->loadKerningPairs(scalingFactor); } else { From 14ef6abd0b8bb877edc0c479cd8a0067a4346c70 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Mon, 25 Jan 2016 11:26:09 +0100 Subject: [PATCH 03/62] Accessibility OS X: protect from accessing invalid objects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Usually when getting an object from an interface, the object can be assumed to be valid. We need to check isValid though since the screen reader access is inherently asynchronous and objects might be in the QWidget destructor where the QObject is still valid. Thus check QAccessibleInterface::isValid in all uses of it in the OS X implementation. Task-number: QTBUG-50545 Change-Id: I6e142f6ead1b3281cab2cbc61ce1406bbfe29f69 Reviewed-by: Morten Johan Sørvig --- .../platforms/cocoa/qcocoaaccessibility.mm | 2 +- .../cocoa/qcocoaaccessibilityelement.mm | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm index 723c341e59d..624220ae5e9 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm @@ -51,7 +51,7 @@ QCocoaAccessibility::~QCocoaAccessibility() void QCocoaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event) { - if (!isActive() || !event->accessibleInterface()) + if (!isActive() || !event->accessibleInterface() || !event->accessibleInterface()->isValid()) return; QMacAccessibilityElement *element = [QMacAccessibilityElement elementWithId: event->uniqueId()]; if (!element) { diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index 608a7583c02..f554bbfe906 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -120,7 +120,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of if (!element) { QAccessibleInterface *iface = QAccessible::accessibleInterface(anId); Q_ASSERT(iface); - if (!iface) + if (!iface || !iface->isValid()) return nil; element = [[self alloc] initWithId:anId]; cache->insertElement(anId, element); @@ -172,7 +172,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of static NSArray *defaultAttributes = nil; QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); - if (!iface) + if (!iface || !iface->isValid()) return defaultAttributes; if (defaultAttributes == nil) { @@ -226,7 +226,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of - (id)parentElement { QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); - if (!iface) + if (!iface || !iface->isValid()) return nil; if (QWindow *window = iface->window()) { @@ -259,7 +259,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of - (id)accessibilityAttributeValue:(NSString *)attribute { QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); - if (!iface) { + if (!iface || !iface->isValid()) { qWarning() << "Called attribute on invalid object: " << axid; return nil; } @@ -354,7 +354,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of - (NSArray *)accessibilityParameterizedAttributeNames { QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); - if (!iface) { + if (!iface || !iface->isValid()) { qWarning() << "Called attribute on invalid object: " << axid; return nil; } @@ -379,7 +379,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of - (id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter { QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); - if (!iface) { + if (!iface || !iface->isValid()) { qWarning() << "Called attribute on invalid object: " << axid; return nil; } @@ -446,7 +446,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of - (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute { QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); - if (!iface) + if (!iface || !iface->isValid()) return NO; if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { @@ -465,7 +465,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of - (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute { QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); - if (!iface) + if (!iface || !iface->isValid()) return; if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { if (QAccessibleActionInterface *action = iface->actionInterface()) @@ -494,7 +494,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of - (NSArray *)accessibilityActionNames { NSMutableArray * nsActions = [NSMutableArray new]; QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); - if (!iface) + if (!iface || !iface->isValid()) return nsActions; const QStringList &supportedActionNames = QAccessibleBridgeUtils::effectiveActionNames(iface); @@ -509,7 +509,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of - (NSString *)accessibilityActionDescription:(NSString *)action { QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); - if (!iface) + if (!iface || !iface->isValid()) return nil; // FIXME is that the right return type?? QString qtAction = QCocoaAccessible::translateAction(action, iface); QString description; From 4c8cb329d458196105d73f08426c8f3b18d61ec7 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Mon, 25 Jan 2016 12:28:25 +0100 Subject: [PATCH 04/62] Accessibility OS X: Fix hang when editing password line edits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a regression when entering data in a password field. The important part is to simply not call convertLineOffset for single line text edits. The reason is that the function when dealing with password fields gets an empty string back when calling textAt etc. This is good since we don't want to leak passwords through a11y apis. The problem with the functions returning empty strings is that we end up in an infinite loop in convertLineOffset. Task-number: QTBUG-49437 Change-Id: I76faa7e33e3ad5c3aeb5c75d8c4b93f1b8227bfc Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index f554bbfe906..081bf927d98 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -336,9 +336,11 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of } else if ([attribute isEqualToString:NSAccessibilityInsertionPointLineNumberAttribute]) { if (QAccessibleTextInterface *text = iface->textInterface()) { - int line = -1; - int position = text->cursorPosition(); - convertLineOffset(text, &line, &position); + int line = 0; // true for all single line edits + if (iface->state().multiLine) { + int position = text->cursorPosition(); + convertLineOffset(text, &line, &position); + } return [NSNumber numberWithInt: line]; } return nil; From 3f482fad3c136b1b2f485dce823985bfa0922a3e Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 27 Jan 2016 08:44:44 +0100 Subject: [PATCH 05/62] Revert some changes to QTextCursor constructors This partially reverts the source and binary incompatible parts of change d921a9bd157b04242722ab4326c5f2ea8e88cbea that made public members in an exported class private and changed signature in one case. Task-number: QTBUG-50703 Change-Id: I2719f276256206347d3c27d80a16db34a4ea2888 Reviewed-by: Lars Knoll --- src/gui/text/qtextcursor.cpp | 4 ++-- src/gui/text/qtextcursor.h | 5 ++--- src/gui/text/qtextcursor_p.h | 2 +- src/gui/text/qtextdocument_p.cpp | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp index dfb6c9c471d..eb51447105c 100644 --- a/src/gui/text/qtextcursor.cpp +++ b/src/gui/text/qtextcursor.cpp @@ -1072,8 +1072,8 @@ QTextCursor::QTextCursor(const QTextBlock &block) /*! \internal */ -QTextCursor::QTextCursor(QTextDocumentPrivate &p, int pos) - : d(new QTextCursorPrivate(&p)) +QTextCursor::QTextCursor(QTextDocumentPrivate *p, int pos) + : d(new QTextCursorPrivate(p)) { d->adjusted_anchor = d->anchor = d->position = pos; diff --git a/src/gui/text/qtextcursor.h b/src/gui/text/qtextcursor.h index c5462b29363..d42d7a1a705 100644 --- a/src/gui/text/qtextcursor.h +++ b/src/gui/text/qtextcursor.h @@ -61,6 +61,8 @@ class Q_GUI_EXPORT QTextCursor public: QTextCursor(); explicit QTextCursor(QTextDocument *document); + QTextCursor(QTextDocumentPrivate *p, int pos); + explicit QTextCursor(QTextCursorPrivate *d); explicit QTextCursor(QTextFrame *frame); explicit QTextCursor(const QTextBlock &block); QTextCursor(const QTextCursor &cursor); @@ -219,9 +221,6 @@ public: QTextDocument *document() const; private: - QTextCursor(QTextDocumentPrivate &p, int pos); - explicit QTextCursor(QTextCursorPrivate *d); - QSharedDataPointer d; friend class QTextCursorPrivate; friend class QTextDocumentPrivate; diff --git a/src/gui/text/qtextcursor_p.h b/src/gui/text/qtextcursor_p.h index 983ff13742a..d3cb52d94f4 100644 --- a/src/gui/text/qtextcursor_p.h +++ b/src/gui/text/qtextcursor_p.h @@ -101,7 +101,7 @@ public: void aboutToRemoveCell(int from, int to); static QTextCursor fromPosition(QTextDocumentPrivate *d, int pos) - { return QTextCursor(*d, pos); } + { return QTextCursor(d, pos); } QTextDocumentPrivate *priv; qreal x; diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp index e5dcfb2e55c..587844c1dd2 100644 --- a/src/gui/text/qtextdocument_p.cpp +++ b/src/gui/text/qtextdocument_p.cpp @@ -1704,7 +1704,7 @@ bool QTextDocumentPrivate::ensureMaximumBlockCount() beginEditBlock(); const int blocksToRemove = blocks.numNodes() - maximumBlockCount; - QTextCursor cursor(*this, 0); + QTextCursor cursor(this, 0); cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor, blocksToRemove); unreachableCharacterCount += cursor.selectionEnd() - cursor.selectionStart(); From 0192ab52e2f14d5914755af5ceb24172f11b6bc7 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 26 Jan 2016 12:28:45 +0100 Subject: [PATCH 06/62] Fix widget texture list locking to avoid animation issues on eglfs QWidgetBackingStore::sync() has two variants. The widget texture list logic was only present in one of them. This led to problems on eglfs in cases when the other variant got invoked. (for instance using the scroll area in the qopenglwidget example) eglfs relies on the texture lists's lock status to properly serialize its somewhat asynchronous built-in compositing mechanism and therefore is the only platform affected. The patch moves the code to be invoked from both sync() variants. Task-number: QTBUG-50668 Change-Id: I4c62987b7bb3cc40f98a4e94447368d2f740dbfd Reviewed-by: Paul Olav Tvete --- src/widgets/kernel/qwidgetbackingstore.cpp | 51 ++++++++++++---------- src/widgets/kernel/qwidgetbackingstore_p.h | 2 + 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index d9d1c887c1f..334b6cd4635 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -1059,6 +1059,31 @@ static inline bool discardSyncRequest(QWidget *tlw, QTLWExtra *tlwExtra) return false; } +bool QWidgetBackingStore::syncAllowed() +{ +#ifndef QT_NO_OPENGL + QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData(); + if (textureListWatcher && !textureListWatcher->isLocked()) { + textureListWatcher->deleteLater(); + textureListWatcher = 0; + } else if (!tlwExtra->widgetTextures.isEmpty()) { + bool skipSync = false; + foreach (QPlatformTextureList *tl, tlwExtra->widgetTextures) { + if (tl->isLocked()) { + if (!textureListWatcher) + textureListWatcher = new QPlatformTextureListWatcher(this); + if (!textureListWatcher->isLocked()) + textureListWatcher->watch(tl); + skipSync = true; + } + } + if (skipSync) // cannot compose due to widget textures being in use + return false; + } +#endif + return true; +} + /*! Synchronizes the \a exposedRegion of the \a exposedWidget with the backing store. @@ -1089,7 +1114,8 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg else markDirtyOnScreen(exposedRegion, exposedWidget, QPoint()); - doSync(); + if (syncAllowed()) + doSync(); } /*! @@ -1115,27 +1141,8 @@ void QWidgetBackingStore::sync() return; } -#ifndef QT_NO_OPENGL - if (textureListWatcher && !textureListWatcher->isLocked()) { - textureListWatcher->deleteLater(); - textureListWatcher = 0; - } else if (!tlwExtra->widgetTextures.isEmpty()) { - bool skipSync = false; - foreach (QPlatformTextureList *tl, tlwExtra->widgetTextures) { - if (tl->isLocked()) { - if (!textureListWatcher) - textureListWatcher = new QPlatformTextureListWatcher(this); - if (!textureListWatcher->isLocked()) - textureListWatcher->watch(tl); - skipSync = true; - } - } - if (skipSync) // cannot compose due to widget textures being in use - return; - } -#endif - - doSync(); + if (syncAllowed()) + doSync(); } void QWidgetBackingStore::doSync() diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h index c45e60ef6ee..564dc7f2456 100644 --- a/src/widgets/kernel/qwidgetbackingstore_p.h +++ b/src/widgets/kernel/qwidgetbackingstore_p.h @@ -164,6 +164,8 @@ private: void updateLists(QWidget *widget); + bool syncAllowed(); + inline void addDirtyWidget(QWidget *widget, const QRegion &rgn) { if (widget && !widget->d_func()->inDirtyList && !widget->data->in_destructor) { From 48ae2dac07fc15cfbcd79632305ba0f88a850459 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 26 Jan 2016 15:48:19 +0100 Subject: [PATCH 07/62] eglfs: fix cleanup when more than one tlw was used There is nothing guaranteeing there is a context current when the backingstore dtor is invoked for widget windows that do not contain render-to-texture widgets. In some cases the eglfs compositor's context is still current, while in other cases (esp. when having popups and other top-levels) there is none. To prevent not releasing the backingstore texture and the incorrect warning about incorrect context, make the correct context current via an offscreen surface, when necessary. Change-Id: Id8257650c1ec8cf96910a4f285b779419c3558a8 Reviewed-by: Paul Olav Tvete --- .../qopenglcompositorbackingstore.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp index fee3146f045..07a1e77c3a9 100644 --- a/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp +++ b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -82,13 +83,28 @@ QOpenGLCompositorBackingStore::~QOpenGLCompositorBackingStore() { if (m_bsTexture) { QOpenGLContext *ctx = QOpenGLContext::currentContext(); + // With render-to-texture-widgets QWidget makes sure the TLW's shareContext() is + // made current before destroying backingstores. That is however not the case for + // windows with regular widgets only. + QScopedPointer tempSurface; + if (!ctx) { + ctx = QOpenGLCompositor::instance()->context(); + tempSurface.reset(new QOffscreenSurface); + tempSurface->setFormat(ctx->format()); + tempSurface->create(); + ctx->makeCurrent(tempSurface.data()); + } + if (ctx && m_bsTextureContext && ctx->shareGroup() == m_bsTextureContext->shareGroup()) glDeleteTextures(1, &m_bsTexture); else qWarning("QOpenGLCompositorBackingStore: Texture is not valid in the current context"); + + if (tempSurface) + ctx->doneCurrent(); } - delete m_textures; + delete m_textures; // this does not actually own any GL resources } QPaintDevice *QOpenGLCompositorBackingStore::paintDevice() @@ -254,6 +270,7 @@ void QOpenGLCompositorBackingStore::resize(const QSize &size, const QRegion &sta if (m_bsTexture) { glDeleteTextures(1, &m_bsTexture); m_bsTexture = 0; + m_bsTextureContext = Q_NULLPTR; } } From 6774edcef0f9f34d41d1156f6c9748f6d9a18930 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Thu, 28 Jan 2016 16:07:13 +0100 Subject: [PATCH 08/62] winrt: set initial window size After creating the swapchain we set an initial size for the content matching the screen size. Only afterwards append it to the canvas. This fixes problems where dialogs were scaled wrongly, sometimes up to 4 times too big. Task-number: QTBUG-50335 Change-Id: Ie3ad9aa3509dfa105ae2ac2b95d2662ff25cdeba Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtwindow.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp index bec94c1e519..034879c4784 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.cpp +++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp @@ -133,6 +133,15 @@ QWinRTWindow::QWinRTWindow(QWindow *window) hr = d->swapChainPanel.As(&d->uiElement); Q_ASSERT_SUCCEEDED(hr); + ComPtr frameworkElement; + hr = d->swapChainPanel.As(&frameworkElement); + Q_ASSERT_SUCCEEDED(hr); + const QSizeF size = QSizeF(d->screen->geometry().size()) / d->screen->scaleFactor(); + hr = frameworkElement->put_Width(size.width()); + Q_ASSERT_SUCCEEDED(hr); + hr = frameworkElement->put_Height(size.height()); + Q_ASSERT_SUCCEEDED(hr); + ComPtr canvas = d->screen->canvas(); ComPtr panel; hr = canvas.As(&panel); From 09e8d69b7a5c6f394b6a43f6c485d26f74189541 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 27 Jan 2016 11:53:25 +0100 Subject: [PATCH 09/62] eglfs: Sanitize the widget compositor's context handling createPlatformOpenGLContext() used to silently set the widget compositor's context as the context to share resources with. This works mostly, but is the wrong level to enforce the resource sharing. For example, QOpenGLContext::shareGroup() becomes inconsistent since from QOpenGLContext's view there was no shareContext specified. The inability to test via shareGroup() is the reason eglfs started to show warnings when exiting applications. The resource sharing was in place on EGL level but QOpenGLContext knew nothing about it. Therefore, let's switch over to the way other components, f.ex. Web Engine use: set the internal global share context pointer to the widget compositor's context. This way everything remains consistent: the widget compositor's context is stored upon creating the main QEGLFSWindow, QWidget::shareContext() picks this up then, and as a result we have sharing set up on QOpenGLContext's level instead of sneaking it in in the QPlatformOpenGLContext implementation. Task-number: QTBUG-50707 Change-Id: I5fc1dec58c69c46aa83c7b4cab1eadce6fa633ce Reviewed-by: Paul Olav Tvete --- .../platformcompositor/qopenglcompositor.cpp | 2 +- .../platformcompositor/qopenglcompositorbackingstore.cpp | 8 ++++++++ src/plugins/platforms/eglfs/qeglfsintegration.cpp | 5 +---- src/plugins/platforms/eglfs/qeglfswindow.cpp | 8 ++++++++ 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/platformsupport/platformcompositor/qopenglcompositor.cpp b/src/platformsupport/platformcompositor/qopenglcompositor.cpp index 2e386532e28..7e0973040ac 100644 --- a/src/platformsupport/platformcompositor/qopenglcompositor.cpp +++ b/src/platformsupport/platformcompositor/qopenglcompositor.cpp @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE It is up to the platform plugin to manage the lifetime of the compositor (instance(), destroy()), set the correct destination - context and window as early as possible (setTargetWindow()), + context and window as early as possible (setTarget()), register the composited windows as they are shown, activated, raised and lowered (addWindow(), moveToTop(), etc.), and to schedule repaints (update()). diff --git a/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp index 07a1e77c3a9..83b551557f1 100644 --- a/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp +++ b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp @@ -184,6 +184,8 @@ void QOpenGLCompositorBackingStore::flush(QWindow *window, const QRegion ®ion QOpenGLCompositor *compositor = QOpenGLCompositor::instance(); QOpenGLContext *dstCtx = compositor->context(); + Q_ASSERT(dstCtx); + QWindow *dstWin = compositor->targetWindow(); if (!dstWin) return; @@ -209,6 +211,12 @@ void QOpenGLCompositorBackingStore::composeAndFlush(QWindow *window, const QRegi QOpenGLCompositor *compositor = QOpenGLCompositor::instance(); QOpenGLContext *dstCtx = compositor->context(); + Q_ASSERT(dstCtx); // setTarget() must have been called before, e.g. from QEGLFSWindow + + // The compositor's context and the context to which QOpenGLWidget/QQuickWidget + // textures belong are not the same. They share resources, though. + Q_ASSERT(context->shareGroup() == dstCtx->shareGroup()); + QWindow *dstWin = compositor->targetWindow(); if (!dstWin) return; diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index 2086ce56e23..35b27cba0bb 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -188,11 +188,8 @@ QPlatformWindow *QEglFSIntegration::createPlatformWindow(QWindow *window) const QPlatformOpenGLContext *QEglFSIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const { - // If there is a "root" window into which raster and QOpenGLWidget content is - // composited, all other contexts must share with its context. - QOpenGLContext *compositingContext = QOpenGLCompositor::instance()->context(); EGLDisplay dpy = context->screen() ? static_cast(context->screen()->handle())->display() : display(); - QPlatformOpenGLContext *share = compositingContext ? compositingContext->handle() : context->shareHandle(); + QPlatformOpenGLContext *share = context->shareHandle(); QVariant nativeHandle = context->nativeHandle(); QEglFSContext *ctx; diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index 8301be8c17f..84856831c39 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -138,6 +138,14 @@ void QEglFSWindow::create() if (!context->create()) qFatal("EGLFS: Failed to create compositing context"); compositor->setTarget(context, window()); + // If there is a "root" window into which raster and QOpenGLWidget content is + // composited, all other contexts must share with its context. + if (!qt_gl_global_share_context()) { + qt_gl_set_global_share_context(context); + // What we set up here is in effect equivalent to the application setting + // AA_ShareOpenGLContexts. Set the attribute to be fully consistent. + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); + } } } From dce530b64eab0666ad22ae5301c2f51b2ee4633f Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 27 Jan 2016 17:02:41 +0100 Subject: [PATCH 10/62] Fix bounding rect of glyph runs in multi-line QTextLayout When getting the glyph runs from a QTextLayout with multiple lines, the glyph runs would be merged if possible, but not their bounding rects. This was an oversight. [ChangeLog][Text][QTextLayout] QTextLayout::glyphRuns() now returns united bounding rects for glyph runs that are merged. Change-Id: Ibbeaa99ecfc4e82e7965342efdae7c3c2b637343 Task-number: QTBUG-50715 Reviewed-by: Konstantin Ritt Reviewed-by: Lars Knoll --- src/gui/text/qtextlayout.cpp | 3 ++ .../auto/gui/text/qglyphrun/tst_qglyphrun.cpp | 29 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 65650504ac6..9e2a23a7f76 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1058,12 +1058,15 @@ QList QTextLayout::glyphRuns(int from, int length) const QVector indexes = oldGlyphRun.glyphIndexes(); QVector positions = oldGlyphRun.positions(); + QRectF boundingRect = oldGlyphRun.boundingRect(); indexes += glyphRun.glyphIndexes(); positions += glyphRun.positions(); + boundingRect = boundingRect.united(glyphRun.boundingRect()); oldGlyphRun.setGlyphIndexes(indexes); oldGlyphRun.setPositions(positions); + oldGlyphRun.setBoundingRect(boundingRect); } else { glyphRunHash[key] = glyphRun; } diff --git a/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp b/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp index 5506c96221f..78cb06986f3 100644 --- a/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp +++ b/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp @@ -70,6 +70,7 @@ private slots: void setRawDataAndGetAsVector(); void boundingRect(); void mixedScripts(); + void multiLineBoundingRect(); private: int m_testFontId; @@ -735,6 +736,34 @@ void tst_QGlyphRun::mixedScripts() QCOMPARE(glyphRuns.size(), 2); } +void tst_QGlyphRun::multiLineBoundingRect() +{ + QTextLayout layout; + layout.setText("Foo Bar"); + layout.beginLayout(); + + QTextLine line = layout.createLine(); + line.setNumColumns(4); + line.setPosition(QPointF(0, 0)); + + line = layout.createLine(); + line.setPosition(QPointF(0, 10)); + + layout.endLayout(); + + QCOMPARE(layout.lineCount(), 2); + + QList firstLineGlyphRuns = layout.lineAt(0).glyphRuns(); + QList allGlyphRuns = layout.glyphRuns(); + QCOMPARE(firstLineGlyphRuns.size(), 1); + QCOMPARE(allGlyphRuns.size(), 1); + + QGlyphRun firstLineGlyphRun = firstLineGlyphRuns.first(); + QGlyphRun allGlyphRun = allGlyphRuns.first(); + + QVERIFY(firstLineGlyphRun.boundingRect().height() < allGlyphRun.boundingRect().height()); +} + #endif // QT_NO_RAWFONT QTEST_MAIN(tst_QGlyphRun) From 2f115fbe0f2ccc0ad25a77c9612588ace9340228 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Fri, 29 Jan 2016 15:24:04 +0100 Subject: [PATCH 11/62] Cocoa integration - fix outdated path in QCocoaFileDialogHelper When we set accessory view sometimes (sic!) a delegate's callback fires: -panel:directoryDidChange: with an outdated path (probably because panels are shared?) resetting our current directory; later we open file dialog with a wrong path as result. Change-Id: Iffb02e801c44c5d9a62c2cca3acdf9278eaadb26 Task-number: QTBUG-50140 Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index 9dc013ba4d8..4c1b190b9c9 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -126,7 +126,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSOpenSavePanelDelegate); if ([mSavePanel respondsToSelector:@selector(setLevel:)]) [mSavePanel setLevel:NSModalPanelWindowLevel]; - [mSavePanel setDelegate:self]; + mReturnCode = -1; mHelper = helper; mNameFilterDropDownList = new QStringList(mOptions->nameFilters()); @@ -147,7 +147,10 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSOpenSavePanelDelegate); [self createTextField]; [self createAccessory]; [mSavePanel setAccessoryView:mNameFilterDropDownList->size() > 1 ? mAccessoryView : nil]; - + // -setAccessoryView: can result in -panel:directoryDidChange: + // resetting our mCurrentDir, set the delegate + // here to make sure it gets the correct value. + [mSavePanel setDelegate:self]; if (mOptions->isLabelExplicitlySet(QFileDialogOptions::Accept)) [mSavePanel setPrompt:[self strip:options->labelText(QFileDialogOptions::Accept)]]; From 758b7b0d88742db7db223a69d689e235e6272f85 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 27 Jan 2016 11:20:45 +0100 Subject: [PATCH 12/62] eglfs: Fix up incorrect comments in the backingstore The note about RasterGLSurface leading to calling composeAndFlush() instead of flush() is simply not true. We have to have visible render-to-texture widgets in the window to enter the composeAndFlush() path. Change-Id: I8331b10c75a3fbefc21009c7e5bb2b4de991bf5a Reviewed-by: Paul Olav Tvete --- .../platformcompositor/qopenglcompositorbackingstore.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp index 83b551557f1..8ec5d20e059 100644 --- a/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp +++ b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp @@ -174,10 +174,7 @@ void QOpenGLCompositorBackingStore::updateTexture() void QOpenGLCompositorBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) { - // Called for ordinary raster windows. This is rare since RasterGLSurface - // support is claimed which leads to having all QWidget windows marked as - // RasterGLSurface instead of just Raster. These go through - // compositeAndFlush() instead of this function. + // Called for ordinary raster windows. Q_UNUSED(region); Q_UNUSED(offset); @@ -202,7 +199,7 @@ void QOpenGLCompositorBackingStore::composeAndFlush(QWindow *window, const QRegi QPlatformTextureList *textures, QOpenGLContext *context, bool translucentBackground) { - // QOpenGLWidget/QQuickWidget content provided as textures. The raster content should go on top. + // QOpenGLWidget/QQuickWidget content provided as textures. The raster content goes on top. Q_UNUSED(region); Q_UNUSED(offset); From 920472c85f6a5cd96344c28dbba0f199c34c6c10 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 27 Jan 2016 18:12:44 +0100 Subject: [PATCH 13/62] Fix clipRect interpretation in composited backingstores Empty clipRect means "clip away completely", not "no clipping". Task-number: QTBUG-50719 Change-Id: I6a9dd66130716a921fe9fc245582274e3c9718fe Reviewed-by: Paul Olav Tvete --- src/gui/painting/qplatformbackingstore.cpp | 8 +++++--- .../platformcompositor/qopenglcompositor.cpp | 6 +++--- tests/manual/qopenglwidget/openglwidget/main.cpp | 7 +++++++ .../qopenglwidget/openglwidget/openglwidget.cpp | 12 +++++++++++- .../manual/qopenglwidget/openglwidget/openglwidget.h | 2 ++ 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index 8e40eb6dff5..5ac903c71df 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -263,12 +263,14 @@ static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight) static void blitTextureForWidget(const QPlatformTextureList *textures, int idx, QWindow *window, const QRect &deviceWindowRect, QOpenGLTextureBlitter *blitter, const QPoint &offset) { + const QRect clipRect = textures->clipRect(idx); + if (clipRect.isEmpty()) + return; + QRect rectInWindow = textures->geometry(idx); // relative to the TLW, not necessarily our window (if the flush is for a native child widget), have to adjust rectInWindow.translate(-offset); - QRect clipRect = textures->clipRect(idx); - if (clipRect.isEmpty()) - clipRect = QRect(QPoint(0, 0), rectInWindow.size()); + const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft()); const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height()); diff --git a/src/platformsupport/platformcompositor/qopenglcompositor.cpp b/src/platformsupport/platformcompositor/qopenglcompositor.cpp index 7e0973040ac..c65d69e8420 100644 --- a/src/platformsupport/platformcompositor/qopenglcompositor.cpp +++ b/src/platformsupport/platformcompositor/qopenglcompositor.cpp @@ -177,11 +177,11 @@ static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight) static void clippedBlit(const QPlatformTextureList *textures, int idx, const QRect &targetWindowRect, QOpenGLTextureBlitter *blitter) { - const QRect rectInWindow = textures->geometry(idx); - QRect clipRect = textures->clipRect(idx); + const QRect clipRect = textures->clipRect(idx); if (clipRect.isEmpty()) - clipRect = QRect(QPoint(0, 0), rectInWindow.size()); + return; + const QRect rectInWindow = textures->geometry(idx); const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft()); const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height()); diff --git a/tests/manual/qopenglwidget/openglwidget/main.cpp b/tests/manual/qopenglwidget/openglwidget/main.cpp index a56cea1dfe6..3844ca3d0f6 100644 --- a/tests/manual/qopenglwidget/openglwidget/main.cpp +++ b/tests/manual/qopenglwidget/openglwidget/main.cpp @@ -181,6 +181,13 @@ int main(int argc, char *argv[]) glw3->setObjectName("GL widget in scroll area (possibly native)"); glw3->setFormat(format); glw3->setFixedSize(600, 600); + OpenGLWidget *glw3child = new OpenGLWidget(0); + const float glw3ClearColor[] = { 0.5f, 0.2f, 0.8f }; + glw3child->setClearColor(glw3ClearColor); + glw3child->setObjectName("Child widget of GL Widget in scroll area"); + glw3child->setFormat(format); + glw3child->setParent(glw3); + glw3child->setGeometry(500, 500, 100, 100); // lower right corner of parent QScrollArea *sa = new QScrollArea; sa->setWidget(glw3); sa->setMinimumSize(100, 100); diff --git a/tests/manual/qopenglwidget/openglwidget/openglwidget.cpp b/tests/manual/qopenglwidget/openglwidget/openglwidget.cpp index 4d2463b84d3..95e2b314050 100644 --- a/tests/manual/qopenglwidget/openglwidget/openglwidget.cpp +++ b/tests/manual/qopenglwidget/openglwidget/openglwidget.cpp @@ -78,6 +78,8 @@ public: int m_interval; QVector3D m_rotAxis; + + float clearColor[3]; }; @@ -85,6 +87,7 @@ OpenGLWidget::OpenGLWidget(int interval, const QVector3D &rotAxis, QWidget *pare : QOpenGLWidget(parent) { d.reset(new OpenGLWidgetPrivate(this)); + d->clearColor[0] = d->clearColor[1] = d->clearColor[2] = 0.0f; d->m_interval = interval; d->m_rotAxis = rotAxis; if (interval > 0) { @@ -151,7 +154,7 @@ void OpenGLWidgetPrivate::render() const qreal retinaScale = q->devicePixelRatio(); glViewport(0, 0, width() * retinaScale, height() * retinaScale); - glClearColor(0.0, 0.0, 0.0, 1.0); + glClearColor(clearColor[0], clearColor[1], clearColor[2], 1.0f); glClear(GL_COLOR_BUFFER_BIT); m_program->bind(); @@ -194,3 +197,10 @@ void OpenGLWidgetPrivate::render() if (m_interval <= 0) q->update(); } + +void OpenGLWidget::setClearColor(const float *c) +{ + d->clearColor[0] = c[0]; + d->clearColor[1] = c[1]; + d->clearColor[2] = c[2]; +} diff --git a/tests/manual/qopenglwidget/openglwidget/openglwidget.h b/tests/manual/qopenglwidget/openglwidget/openglwidget.h index a1d54908458..1b9a66d8778 100644 --- a/tests/manual/qopenglwidget/openglwidget/openglwidget.h +++ b/tests/manual/qopenglwidget/openglwidget/openglwidget.h @@ -49,6 +49,8 @@ public: void resizeGL(int w, int h); void paintGL(); + void setClearColor(const float *c); + private: QScopedPointer d; }; From 8fd093e47c44f4efc63a80d3ddcdc138afb8230c Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 21 May 2015 10:15:36 +0200 Subject: [PATCH 14/62] support specifying directories in RESOURCES Change-Id: Ie97b26dd8ccf33d7f2a72bc6a5aec478b196ebb6 Reviewed-by: Rainer Keller Reviewed-by: hjk (cherry picked from commit 4b224816aa2902e10835a560d14e305cfdc32bac) --- mkspecs/features/resources.prf | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/mkspecs/features/resources.prf b/mkspecs/features/resources.prf index 7a38ff8f380..1f04c8b0d71 100644 --- a/mkspecs/features/resources.prf +++ b/mkspecs/features/resources.prf @@ -49,9 +49,15 @@ for(resource, RESOURCES) { for(file, $${resource}.files) { abs_path = $$absolute_path($$file, $$_PRO_FILE_PWD_) - alias = $$relative_path($$abs_path, $$abs_base) - resource_file_content += \ - "$$xml_escape($$abs_path)" + files = $$files($$abs_path/*, true) + isEmpty(files): \ + files = $$abs_path + for (file, files) { + exists($$file/*): next() # exclude directories + alias = $$relative_path($$file, $$abs_base) + resource_file_content += \ + "$$xml_escape($$file)" + } } resource_file_content += \ From b5ea7a5f5c849329643112cba9b57ad047c0bc4b Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Fri, 18 Dec 2015 00:33:42 +0100 Subject: [PATCH 15/62] Add missing emission of activated(QString) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This signal got missed when 3fb0d851a was submitted so this compliments that fix. Change-Id: I91d20b709fce2c78d41166779954a3bb618feb37 Reviewed-by: Timur Pocheptsov Reviewed-by: Tor Arne Vestbø --- src/widgets/widgets/qcombobox.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index b04aa7053a4..3290cec604f 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -2429,6 +2429,7 @@ struct IndexSetter { { cb->setCurrentIndex(index); emit cb->activated(index); + emit cb->activated(cb->itemText(index)); } }; } From 09559b5b7991aa94529ad8ee8fe311427fe83834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 1 Feb 2016 17:31:33 +0100 Subject: [PATCH 16/62] BIC: Rename back symbol that was mistakenly thought to be private MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Being called from an inline function we were breaking BIC (however insignificant) by renaming the symbol in c7e5e1d9e0. Change-Id: I683bfd53a5ad0de7db0fae6d9aa7d175e00f96ed Reviewed-by: Jędrzej Nowacki --- src/gui/kernel/qwindowsysteminterface.cpp | 2 +- src/testlib/qtestkeyboard.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index a9dcb8bb7d3..4bbc303ac04 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -868,7 +868,7 @@ Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::Keybo QWindowSystemInterface::setSynchronousWindowSystemEvents(wasSynchronous); } -Q_GUI_EXPORT bool qt_handleShortcutEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1) +Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1) { #ifndef QT_NO_SHORTCUT diff --git a/src/testlib/qtestkeyboard.h b/src/testlib/qtestkeyboard.h index aa117ed7dee..f80a72e2dfb 100644 --- a/src/testlib/qtestkeyboard.h +++ b/src/testlib/qtestkeyboard.h @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); -Q_GUI_EXPORT bool qt_handleShortcutEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1); +Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1); namespace QTest { @@ -93,7 +93,7 @@ namespace QTest if (action == Shortcut) { int timestamp = 0; - qt_handleShortcutEvent(window, timestamp, code, modifier, text, repeat); + qt_sendShortcutOverrideEvent(window, timestamp, code, modifier, text, repeat); return; } @@ -174,7 +174,7 @@ namespace QTest QKeyEvent a(press ? QEvent::KeyPress : QEvent::KeyRelease, code, modifier, text, repeat); QSpontaneKeyEvent::setSpontaneous(&a); - if (press && qt_handleShortcutEvent(widget, a.timestamp(), code, modifier, text, repeat)) + if (press && qt_sendShortcutOverrideEvent(widget, a.timestamp(), code, modifier, text, repeat)) return; if (!qApp->notify(widget, &a)) QTest::qWarn("Keyboard event not accepted by receiving widget"); From e5e9387f9a4070a250a6e806ede37453d5368c69 Mon Sep 17 00:00:00 2001 From: Samuli Piippo Date: Thu, 21 Jan 2016 13:20:42 +0200 Subject: [PATCH 17/62] Use extra compilers for the linker version script This ensures correct separator handling and quoting. Change-Id: I0f9cc7024cac579ea4c81f0c28754b1424ae2bd4 Reviewed-by: Oswald Buddenhagen --- mkspecs/features/qt_module.prf | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf index e543ea65e64..bb28af975f1 100644 --- a/mkspecs/features/qt_module.prf +++ b/mkspecs/features/qt_module.prf @@ -194,7 +194,7 @@ equals(QT_ARCH, i386):contains(QT_CPU_FEATURES.$$QT_ARCH, sse2):compiler_support android: CONFIG += qt_android_deps no_linker_version_script !header_module:unix:!isEmpty(QMAKE_LFLAGS_VERSION_SCRIPT):!no_linker_version_script:!static { - verscript = $$OUT_PWD/$${TARGET}.version + verscript = $${TARGET}.version QMAKE_LFLAGS += $${QMAKE_LFLAGS_VERSION_SCRIPT}$$verscript internal_module { @@ -219,16 +219,20 @@ android: CONFIG += qt_android_deps no_linker_version_script } # Add a post-processing step to replace the @FILE:filename@ - verscriptprocess.commands = perl $${PWD}/data/unix/findclasslist.pl < $${verscript}.in > $@ - verscriptprocess.target = $$verscript + verscript_in = $${verscript}.in + verscriptprocess.name = linker version script ${QMAKE_FILE_BASE} + verscriptprocess.input = verscript_in + verscriptprocess.CONFIG += no_link target_predeps for(header, SYNCQT.PRIVATE_HEADER_FILES): \ verscriptprocess.depends += $${_PRO_FILE_PWD_}/$$header - verscriptprocess.depends += $${verscript}.in - QMAKE_EXTRA_TARGETS += verscriptprocess - PRE_TARGETDEPS += $$verscript - verscript = $${verscript}.in + verscriptprocess.output = $$verscript + verscriptprocess.commands = perl $${PWD}/data/unix/findclasslist.pl < ${QMAKE_FILE_IN} > $@ + silent:verscriptprocess.commands = @echo creating linker version script ${QMAKE_FILE_BASE} && $$verscriptprocess.commands + QMAKE_EXTRA_COMPILERS += verscriptprocess + + verscript = $$verscript_in } - write_file($$verscript, verscript_content)|error("Aborting.") + write_file($$OUT_PWD/$$verscript, verscript_content)|error("Aborting.") unset(current) unset(previous) unset(verscript) From 46c73be4710a6aa1be84a19151f73d87413a52b4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 30 Jan 2016 09:48:41 -0800 Subject: [PATCH 18/62] Fix livelock at application exit if threads were running This only happened in debug mode, though, because in release mode the warning wasn't printed and the socket notifier was removed. In debug mode, this loop in closingDown() never exited: while (!d->sn_read.isEmpty()) unregisterSocketNotifier((*(d->sn_read.begin()))->obj); [ChangeLog][QtCore][QThread] Fixed a bug that would cause debug-mode applications to live lock on exit if they had a global static containing a QThread that wasn't properly exited. Task-number: QTBUG-49870 Change-Id: I7a9e11d7b64a4cc78e24ffff142e457a4540d6b6 Reviewed-by: Mat Sutcliffe Reviewed-by: Roland Winklmeier Reviewed-by: Friedemann Kleint --- src/corelib/kernel/qeventdispatcher_win.cpp | 17 ++++++++++++----- src/corelib/kernel/qeventdispatcher_win_p.h | 1 + 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 1a14500bd42..b3df139743e 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -935,9 +935,8 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier) void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) { Q_ASSERT(notifier); - int sockfd = notifier->socket(); - int type = notifier->type(); #ifndef QT_NO_DEBUG + int sockfd = notifier->socket(); if (sockfd < 0) { qWarning("QSocketNotifier: Internal error"); return; @@ -946,8 +945,16 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) return; } #endif + doUnregisterSocketNotifier(notifier); +} +void QEventDispatcherWin32::doUnregisterSocketNotifier(QSocketNotifier *notifier) +{ Q_D(QEventDispatcherWin32); + int type = notifier->type(); + int sockfd = notifier->socket(); + Q_ASSERT(sockfd >= 0); + QSFDict::iterator it = d->active_fd.find(sockfd); if (it != d->active_fd.end()) { QSockFd &sd = it.value(); @@ -1203,11 +1210,11 @@ void QEventDispatcherWin32::closingDown() // clean up any socketnotifiers while (!d->sn_read.isEmpty()) - unregisterSocketNotifier((*(d->sn_read.begin()))->obj); + doUnregisterSocketNotifier((*(d->sn_read.begin()))->obj); while (!d->sn_write.isEmpty()) - unregisterSocketNotifier((*(d->sn_write.begin()))->obj); + doUnregisterSocketNotifier((*(d->sn_write.begin()))->obj); while (!d->sn_except.isEmpty()) - unregisterSocketNotifier((*(d->sn_except.begin()))->obj); + doUnregisterSocketNotifier((*(d->sn_except.begin()))->obj); Q_ASSERT(d->active_fd.isEmpty()); // clean up any timers diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index 9a53e067302..222562dfceb 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -103,6 +103,7 @@ public: protected: QEventDispatcherWin32(QEventDispatcherWin32Private &dd, QObject *parent = 0); virtual void sendPostedEvents(); + void doUnregisterSocketNotifier(QSocketNotifier *notifier); private: friend LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp); From 3726c46735edb23ad37af818ff7d52d661ec87e7 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 29 Jan 2016 13:41:38 -0800 Subject: [PATCH 19/62] Work around Clang < 3.7 integrated assembler bug PC-relative relocs The qversiontagging.h inline assembly expands to: .long qt_version_tag@GOTPCREL Which, with GCC, Clang >= 3.7 and with the option -no-integrated-as in previous versions, produces the proper relocation (a R_X86_64_GOTPCREL). With Clang < 3.7, it instead produces a R_X86_64_32, which is unsuitable for use in shared libraries: 32-bit displacement is insufficiently wide and would produce linker errors like obj/qftp.o: requires dynamic R_X86_64_32 reloc against 'qt_version_tag' which may overflow at runtime; recompile with -fPIC Instead, force a 64-bit relocation (an R_X86_64_GOT64), which like the 32-bit version is simply an offset into the GOT of where the address of the symbol is stored. Task-number: QTBUG-50749 Change-Id: I7a9e11d7b64a4cc78e24ffff142e039c172b802c Reviewed-by: Simon Hausmann --- src/corelib/global/qversiontagging.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/corelib/global/qversiontagging.h b/src/corelib/global/qversiontagging.h index d6b4a656003..953f669501b 100644 --- a/src/corelib/global/qversiontagging.h +++ b/src/corelib/global/qversiontagging.h @@ -59,11 +59,7 @@ QT_BEGIN_NAMESPACE #elif defined(Q_CC_GNU) && !defined(Q_OS_ANDROID) # if defined(Q_PROCESSOR_X86) && (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD_KERNEL)) # if defined(Q_PROCESSOR_X86_64) // x86-64 or x32 -# if defined(__code_model_large__) -# define QT_VERSION_TAG_RELOC(sym) ".quad " QT_STRINGIFY(QT_MANGLE_NAMESPACE(sym)) "@GOT\n" -# else -# define QT_VERSION_TAG_RELOC(sym) ".long " QT_STRINGIFY(QT_MANGLE_NAMESPACE(sym)) "@GOTPCREL\n" -# endif +# define QT_VERSION_TAG_RELOC(sym) ".quad " QT_STRINGIFY(QT_MANGLE_NAMESPACE(sym)) "@GOT\n" # else // x86 # define QT_VERSION_TAG_RELOC(sym) ".long " QT_STRINGIFY(QT_MANGLE_NAMESPACE(sym)) "@GOT\n" # endif From ccf74b592809e0c5a613eff27d6431a4c659e368 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 29 Jan 2016 13:27:53 -0800 Subject: [PATCH 20/62] Fix build on FreeBSD: 'environ' is not defined in a library On FreeBSD, this variable is defined as a common symbol in the object file /usr/lib/crt1.o, which is injected into the final application by the compiler. This means when linking any library, 'environ' cannot be found and we can't use -Wl,-no-undefined on FreeBSD. I don't know why this wasn't caught before. Most likely, we failed to pass the linker flag until some recent change to the buildsystem. qprocess_unix.cpp:279: undefined reference to `environ' Change-Id: I7a9e11d7b64a4cc78e24ffff142e02dbf188bca5 Reviewed-by: Simon Hausmann Reviewed-by: Oswald Buddenhagen --- src/corelib/corelib.pro | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index 5cd0bde87bf..ab3f29e2c7b 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -27,6 +27,10 @@ ANDROID_PERMISSIONS = \ android.permission.INTERNET \ android.permission.WRITE_EXTERNAL_STORAGE +# QtCore can't be compiled with -Wl,-no-undefined because it uses the "environ" +# variable and on FreeBSD, this variable is in the final executable itself +freebsd: QMAKE_LFLAGS_NOUNDEF = + load(qt_module) load(qfeatures) From 628d3b7d3a5646d4d1503c1c0fdef0e51bc5129b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 29 Jan 2016 11:20:50 -0800 Subject: [PATCH 21/62] Swap the GCC and Clang versions of supported FreeBSD mkspecs Modern FreeBSD doesn't come with GCC by default anymore and doesn't even provide the "gcc" or "g++" falback that OS X does. So there's no point in keeping the freebsd-clang mkspec in unsupported/ since it's the only one that works, or keeping the freebsd-g++* ones outside, as they won't compile. I'm not removing the GCC mkspecs because you can still install GCC from the ports tree. [ChangeLog][FreeBSD] The "freebsd-clang" mkspec is no longer in the unsupported/ subdir. If you have scripts you use to build Qt, you'll need to update them to say -platform freebsd-clang or remove the -platform argument. Change-Id: I7a9e11d7b64a4cc78e24ffff142dfc11d3aabb1e Reviewed-by: Raphael Kubo da Costa Reviewed-by: Simon Hausmann Reviewed-by: Oswald Buddenhagen --- configure | 2 +- mkspecs/{unsupported => }/freebsd-clang/qmake.conf | 4 ++-- mkspecs/{freebsd-g++ => freebsd-clang}/qplatformdefs.h | 0 mkspecs/{ => unsupported}/freebsd-g++/qmake.conf | 6 +++--- .../{freebsd-clang => freebsd-g++}/qplatformdefs.h | 2 +- mkspecs/{ => unsupported}/freebsd-g++46/qmake.conf | 6 +++--- mkspecs/{ => unsupported}/freebsd-g++46/qplatformdefs.h | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) rename mkspecs/{unsupported => }/freebsd-clang/qmake.conf (91%) rename mkspecs/{freebsd-g++ => freebsd-clang}/qplatformdefs.h (100%) rename mkspecs/{ => unsupported}/freebsd-g++/qmake.conf (87%) rename mkspecs/unsupported/{freebsd-clang => freebsd-g++}/qplatformdefs.h (97%) rename mkspecs/{ => unsupported}/freebsd-g++46/qmake.conf (90%) rename mkspecs/{ => unsupported}/freebsd-g++46/qplatformdefs.h (97%) diff --git a/configure b/configure index 0c579b3e747..7651e295ecc 100755 --- a/configure +++ b/configure @@ -2854,7 +2854,7 @@ if [ -z "$PLATFORM" ]; then PLATFORM=ultrix-g++ ;; FreeBSD:*) - PLATFORM=freebsd-g++ + PLATFORM=freebsd-clang PLATFORM_NOTES=" - Also available for FreeBSD: freebsd-icc " diff --git a/mkspecs/unsupported/freebsd-clang/qmake.conf b/mkspecs/freebsd-clang/qmake.conf similarity index 91% rename from mkspecs/unsupported/freebsd-clang/qmake.conf rename to mkspecs/freebsd-clang/qmake.conf index 9d9815a7b3b..7f18bbb7211 100644 --- a/mkspecs/unsupported/freebsd-clang/qmake.conf +++ b/mkspecs/freebsd-clang/qmake.conf @@ -30,7 +30,7 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../../common/gcc-base-unix.conf) -include(../../common/clang.conf) +include(../common/gcc-base-unix.conf) +include(../common/clang.conf) load(qt_config) diff --git a/mkspecs/freebsd-g++/qplatformdefs.h b/mkspecs/freebsd-clang/qplatformdefs.h similarity index 100% rename from mkspecs/freebsd-g++/qplatformdefs.h rename to mkspecs/freebsd-clang/qplatformdefs.h diff --git a/mkspecs/freebsd-g++/qmake.conf b/mkspecs/unsupported/freebsd-g++/qmake.conf similarity index 87% rename from mkspecs/freebsd-g++/qmake.conf rename to mkspecs/unsupported/freebsd-g++/qmake.conf index 282b6bdfa7c..527a94870c9 100644 --- a/mkspecs/freebsd-g++/qmake.conf +++ b/mkspecs/unsupported/freebsd-g++/qmake.conf @@ -5,7 +5,7 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = freebsd bsd -include(../common/unix.conf) +include(../../common/unix.conf) QMAKE_CFLAGS_THREAD = -pthread -D_THREAD_SAFE @@ -29,6 +29,6 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/gcc-base-unix.conf) -include(../common/g++-unix.conf) +include(../../common/gcc-base-unix.conf) +include(../../common/g++-unix.conf) load(qt_config) diff --git a/mkspecs/unsupported/freebsd-clang/qplatformdefs.h b/mkspecs/unsupported/freebsd-g++/qplatformdefs.h similarity index 97% rename from mkspecs/unsupported/freebsd-clang/qplatformdefs.h rename to mkspecs/unsupported/freebsd-g++/qplatformdefs.h index 68a886ed897..b52be38b4ed 100644 --- a/mkspecs/unsupported/freebsd-clang/qplatformdefs.h +++ b/mkspecs/unsupported/freebsd-g++/qplatformdefs.h @@ -31,4 +31,4 @@ ** ****************************************************************************/ -#include "../../freebsd-g++/qplatformdefs.h" +#include "../../freebsd-clang/qplatformdefs.h" diff --git a/mkspecs/freebsd-g++46/qmake.conf b/mkspecs/unsupported/freebsd-g++46/qmake.conf similarity index 90% rename from mkspecs/freebsd-g++46/qmake.conf rename to mkspecs/unsupported/freebsd-g++46/qmake.conf index b930fca78b5..11041dee3d2 100644 --- a/mkspecs/freebsd-g++46/qmake.conf +++ b/mkspecs/unsupported/freebsd-g++46/qmake.conf @@ -5,7 +5,7 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = freebsd bsd -include(../common/unix.conf) +include(../../common/unix.conf) QMAKE_CFLAGS_THREAD = -pthread -D_THREAD_SAFE @@ -29,8 +29,8 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/gcc-base-unix.conf) -include(../common/g++-unix.conf) +include(../../common/gcc-base-unix.conf) +include(../../common/g++-unix.conf) # Redefined here because g++-base.conf sets QMAKE_CC and QMAKE_CXX # to gcc and g++, respectively. diff --git a/mkspecs/freebsd-g++46/qplatformdefs.h b/mkspecs/unsupported/freebsd-g++46/qplatformdefs.h similarity index 97% rename from mkspecs/freebsd-g++46/qplatformdefs.h rename to mkspecs/unsupported/freebsd-g++46/qplatformdefs.h index 48dc4d64fb0..b52be38b4ed 100644 --- a/mkspecs/freebsd-g++46/qplatformdefs.h +++ b/mkspecs/unsupported/freebsd-g++46/qplatformdefs.h @@ -31,4 +31,4 @@ ** ****************************************************************************/ -#include "../freebsd-g++/qplatformdefs.h" +#include "../../freebsd-clang/qplatformdefs.h" From 38e602d0f2e4c292296d603fda22b366d8879daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Nowacki?= Date: Tue, 26 Jan 2016 13:46:28 +0100 Subject: [PATCH 22/62] Fix QT_DEPRECATED_SINCE usage The deprecation was introduced in 5.6 Change-Id: Ief6b749b40ec75c3c9f904caed8447bfb5ef5439 Reviewed-by: Marc Mutz Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/tools/qshareddata.h | 2 +- src/corelib/tools/qsharedpointer_impl.h | 2 +- src/dbus/qdbusextratypes.h | 2 +- src/gui/kernel/qopenglcontext.h | 2 +- src/gui/opengl/qopenglversionfunctions.h | 2 +- src/network/ssl/qsslellipticcurve.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h index 6a0900cf3f0..bc81135d7a8 100644 --- a/src/corelib/tools/qshareddata.h +++ b/src/corelib/tools/qshareddata.h @@ -36,7 +36,7 @@ #include #include -#if QT_DEPRECATED_SINCE(5, 5) +#if QT_DEPRECATED_SINCE(5, 6) #include #endif #include diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index bd98cb326ca..70b100d018a 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -55,7 +55,7 @@ QT_END_NAMESPACE #include #include #include // for qobject_cast -#if QT_DEPRECATED_SINCE(5, 5) +#if QT_DEPRECATED_SINCE(5, 6) #include #endif #include diff --git a/src/dbus/qdbusextratypes.h b/src/dbus/qdbusextratypes.h index 8495b3a3206..adbc371fdf9 100644 --- a/src/dbus/qdbusextratypes.h +++ b/src/dbus/qdbusextratypes.h @@ -39,7 +39,7 @@ #include #include #include -#if QT_DEPRECATED_SINCE(5, 5) +#if QT_DEPRECATED_SINCE(5, 6) #include #endif #include diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h index 841967a5453..a658f24ac5e 100644 --- a/src/gui/kernel/qopenglcontext.h +++ b/src/gui/kernel/qopenglcontext.h @@ -54,7 +54,7 @@ #include #include -#if QT_DEPRECATED_SINCE(5, 5) +#if QT_DEPRECATED_SINCE(5, 6) #include #endif #include diff --git a/src/gui/opengl/qopenglversionfunctions.h b/src/gui/opengl/qopenglversionfunctions.h index a5d5677938e..695fc760524 100644 --- a/src/gui/opengl/qopenglversionfunctions.h +++ b/src/gui/opengl/qopenglversionfunctions.h @@ -47,7 +47,7 @@ #ifndef QT_NO_OPENGL -#if QT_DEPRECATED_SINCE(5, 5) +#if QT_DEPRECATED_SINCE(5, 6) #include #endif #include diff --git a/src/network/ssl/qsslellipticcurve.h b/src/network/ssl/qsslellipticcurve.h index 5716e3447d1..c57453d41f4 100644 --- a/src/network/ssl/qsslellipticcurve.h +++ b/src/network/ssl/qsslellipticcurve.h @@ -37,7 +37,7 @@ #include #include #include -#if QT_DEPRECATED_SINCE(5, 5) +#if QT_DEPRECATED_SINCE(5, 6) #include #endif #include From cb6d4d1f16215694547514a6342e47854534223e Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 4 Feb 2016 10:18:42 +0100 Subject: [PATCH 23/62] Revert "QWidgetWindow: call base class close event impl". The patch causes the window creation on reshowing nested QWidget with native windows to create child windows with 0-parent handles, which can have adverse effects on the various platforms. The patch might be re-applied on top of 73c86fcb400cb91868b56ac05a3b82a3f7ba1a1b. This reverts commit 470c8b68df539ca7356cd6b8596f8323ba3ed779. Task-number: QTBUG-43344 Task-number: QTBUG-50854 Change-Id: I2ad837c3800fc71cccf04d455d1b9c3600b233e7 Reviewed-by: Laszlo Agocs Reviewed-by: Andy Shaw --- src/widgets/kernel/qwidgetwindow.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 6f8d97e0289..0de0fe21f26 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -708,7 +708,6 @@ void QWidgetWindow::handleCloseEvent(QCloseEvent *event) { bool is_closing = m_widget->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent); event->setAccepted(is_closing); - QWindow::event(event); // Call QWindow QCloseEvent handler. } #ifndef QT_NO_WHEELEVENT From d482805856a83f39fdab32c76f10cf7d7d5e2112 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 4 Feb 2016 10:15:59 +0100 Subject: [PATCH 24/62] Do not change depth for the backingstore's underlying image The depth cannot change. This means that RGB16 cannot be upgraded to 8565 for example as that would be a 24 bit format whereas the backingstores and the underlying platform may expect a 16 bit format. Task-number: QTBUG-50869 Change-Id: I648b39287d43a80fae8097a33bbf3b8bbdcb8816 Reviewed-by: Friedemann Kleint Reviewed-by: Andreas Holzammer Reviewed-by: Allan Sandfeld Jensen --- src/gui/image/qimage_p.h | 6 ++++++ src/plugins/platforms/windows/qwindowsbackingstore.cpp | 2 +- src/plugins/platforms/xcb/qxcbbackingstore.cpp | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h index f9ad6c0ac0d..0c0653e8abc 100644 --- a/src/gui/image/qimage_p.h +++ b/src/gui/image/qimage_p.h @@ -189,6 +189,12 @@ inline QImage::Format qt_alphaVersion(QImage::Format format) return QImage::Format_ARGB32_Premultiplied; } +inline QImage::Format qt_maybeAlphaVersionWithSameDepth(QImage::Format format) +{ + const QImage::Format toFormat = qt_alphaVersion(format); + return qt_depthForFormat(format) == qt_depthForFormat(toFormat) ? toFormat : format; +} + inline QImage::Format qt_alphaVersionForPainting(QImage::Format format) { QImage::Format toFormat = qt_alphaVersion(format); diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp index a6b1d0af267..af9d2a59691 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp +++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp @@ -155,7 +155,7 @@ void QWindowsBackingStore::resize(const QSize &size, const QRegion ®ion) if (QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha) m_alphaNeedsFill = true; else // upgrade but here we know app painting does not rely on alpha hence no need to fill - format = qt_alphaVersionForPainting(format); + format = qt_maybeAlphaVersionWithSameDepth(format); QWindowsNativeImage *oldwni = m_image.data(); QWindowsNativeImage *newwni = new QWindowsNativeImage(size.width(), size.height(), format); diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index c34bea02423..3b04c59e28b 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -179,7 +179,7 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI m_hasAlpha = QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha; if (!m_hasAlpha) - format = qt_alphaVersionForPainting(format); + format = qt_maybeAlphaVersionWithSameDepth(format); m_qimage = QImage( (uchar*) m_xcb_image->data, m_xcb_image->width, m_xcb_image->height, m_xcb_image->stride, format); m_graphics_buffer = new QXcbShmGraphicsBuffer(&m_qimage); From 786d23bb4966b6697ac04c43158e2312d898e133 Mon Sep 17 00:00:00 2001 From: Andreas Holzammer Date: Wed, 3 Feb 2016 11:53:57 +0100 Subject: [PATCH 25/62] Fix dbus wince build interface is a define under wince. This define is included even with standard header includes already. It needs to be undefined for using it. Task-number: QTBUG-50853 Change-Id: Ie44681f03709848e9747a8aec11835c8d62aa409 Reviewed-by: Lars Knoll Reviewed-by: Thiago Macieira --- src/dbus/qdbusabstractinterface.h | 4 ++++ src/dbus/qdbusconnection.cpp | 4 ++++ src/dbus/qdbusintegrator.cpp | 3 +++ 3 files changed, 11 insertions(+) diff --git a/src/dbus/qdbusabstractinterface.h b/src/dbus/qdbusabstractinterface.h index 5336dfba388..16071df9564 100644 --- a/src/dbus/qdbusabstractinterface.h +++ b/src/dbus/qdbusabstractinterface.h @@ -43,6 +43,10 @@ #include #include +#ifdef interface +#undef interface +#endif + #ifndef QT_NO_DBUS QT_BEGIN_NAMESPACE diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index 0f2d799b922..7f44272bc33 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -54,6 +54,10 @@ #include +#ifdef interface +#undef interface +#endif + #ifndef QT_NO_DBUS QT_BEGIN_NAMESPACE diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index ebf42b0b06a..cd448613d65 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -63,6 +63,9 @@ #include "qdbusthreaddebug_p.h" #include +#ifdef interface +#undef interface +#endif #ifndef QT_NO_DBUS From e4f71b0cb5e52b4762c4c1d681eff08376e7bc0b Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Tue, 2 Feb 2016 14:06:28 +0100 Subject: [PATCH 26/62] Crash fix: reject certain malformed bmp images A malformed bmp file header could specify a negative color table size. The bmp handler would then return a QImage that claimed to be valid, but actually was invalid, having an empty color table. This would cause crash later, e.g. when attempting to paint it. Change-Id: I7df7c40867557a82dbcee44c7de061226ff232c0 Reviewed-by: Lars Knoll Reviewed-by: Richard J. Moore --- src/gui/image/qbmphandler.cpp | 2 +- .../image/qimagereader/images/corrupt_clut.bmp | Bin 0 -> 368 bytes .../gui/image/qimagereader/tst_qimagereader.cpp | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 tests/auto/gui/image/qimagereader/images/corrupt_clut.bmp diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp index ef12b23caa6..27bab10196c 100644 --- a/src/gui/image/qbmphandler.cpp +++ b/src/gui/image/qbmphandler.cpp @@ -294,7 +294,7 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int if (depth != 32) { ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits; - if (ncols > 256) // sanity check - don't run out of mem if color table is broken + if (ncols < 1 || ncols > 256) // sanity check - don't run out of mem if color table is broken return false; image.setColorCount(ncols); } diff --git a/tests/auto/gui/image/qimagereader/images/corrupt_clut.bmp b/tests/auto/gui/image/qimagereader/images/corrupt_clut.bmp new file mode 100644 index 0000000000000000000000000000000000000000..aeb063fce5547720f174f19964f591fac6fa25e4 GIT binary patch literal 368 zcmZ?r)nZ~gs{b*0wi^q>R0jqI1`Z&WVq{=o1hRk>7z;A8fM`Z(28Nse8!BD)KqNRA z>gGNK@?Nk%chfQHeCSj(WoCV7$}UlFE|VQAlXme|TkUiCa>e}446#ZX{%cuMdF~E} zrmII^<;_s^JoUbF^QN}hm!BP-%Hz)3rfs}?>XiM zk~VLJ85o$D!7kAQxrh Date: Tue, 26 Jan 2016 15:17:09 +0100 Subject: [PATCH 27/62] Scale offset as well on QBackingStore flush MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also use the target window ("win") as context instead of d->window. Change-Id: I5b0fa3bb857526e4a4bc9c5e44670593da1dfe7c Task-number: QTBUG-50487 Reviewed-by: Friedemann Kleint Reviewed-by: Morten Johan Sørvig Reviewed-by: Paul Olav Tvete --- src/gui/painting/qbackingstore.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index 8a5a6d4fcf1..c39675b0b6b 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -106,7 +106,8 @@ void QBackingStore::flush(const QRegion ®ion, QWindow *win, const QPoint &off } #endif - d_ptr->platformBackingStore->flush(win, QHighDpi::toNativeLocalRegion(region, d_ptr->window), offset); + d_ptr->platformBackingStore->flush(win, QHighDpi::toNativeLocalRegion(region, win), + QHighDpi::toNativeLocalPosition(offset, win)); } /*! From 4c1b6cdd292bc571a4104fff8b5b54d47970cca1 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 5 Feb 2016 09:56:49 +0100 Subject: [PATCH 28/62] Support arbitrary strides in the QPlatformBackingStore compositor Otherwise platform backingstores providing QImages with extra pixels would break horribly. The only such platform is wayland for now. Previously the need to support this case was masked by the RGBA8888 image conversion that happened always with wayland due to its ARGB32_Pre format. With the recent improvements this is not done anymore and so the problems became apparent. Task-number: QTBUG-50894 Change-Id: I27d7a1c8e25d152ca1227af1e2c38f7d4b6acbab Reviewed-by: Paul Olav Tvete --- src/gui/painting/qplatformbackingstore.cpp | 25 ++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index 5ac903c71df..33d5e76e52b 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -516,7 +516,23 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu if (needsConversion) image = image.convertToFormat(QImage::Format_RGBA8888); + // The image provided by the backingstore may have a stride larger than width * 4, for + // instance on platforms that manually implement client-side decorations. + static const int bytesPerPixel = 4; + const int strideInPixels = image.bytesPerLine() / bytesPerPixel; + const bool hasUnpackRowLength = !ctx->isOpenGLES() || ctx->format().majorVersion() >= 3; + QOpenGLFunctions *funcs = ctx->functions(); + + if (hasUnpackRowLength) { + funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, strideInPixels); + } else if (strideInPixels != image.width()) { + // No UNPACK_ROW_LENGTH on ES 2.0 and yet we would need it. This case is typically + // hit with QtWayland which is rarely used in combination with a ES2.0-only GL + // implementation. Therefore, accept the performance hit and do a copy. + image = image.copy(); + } + if (resized) { if (d_ptr->textureId) funcs->glDeleteTextures(1, &d_ptr->textureId); @@ -538,11 +554,9 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu QRect imageRect = image.rect(); QRect rect = dirtyRegion.boundingRect() & imageRect; - if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { - funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, image.width()); + if (hasUnpackRowLength) { funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType, - image.constScanLine(rect.y()) + rect.x() * 4); - funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + image.constScanLine(rect.y()) + rect.x() * bytesPerPixel); } else { // if the rect is wide enough it's cheaper to just // extend it instead of doing an image copy @@ -564,6 +578,9 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu } } + if (hasUnpackRowLength) + funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + return d_ptr->textureId; } #endif // QT_NO_OPENGL From f5b9cdbb0844dd149d9b945b28da42d56977f844 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 8 Feb 2016 14:32:18 +0100 Subject: [PATCH 29/62] HighDPI: Extend exposed region to avoid artifacts by rounding. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a special scaling function fromNativeLocalExposedRegion() for exposed regions that uses the floor of the top left point and the ceiling of the bottom right point similarly to how it was done in the XCB plugin in 5.5. Task-number: QTBUG-46615 Task-number: QTBUG-50463 Change-Id: I95e4a571b814357c014605ed79e374a821fa155b Reviewed-by: Błażej Szczygieł Reviewed-by: Morten Johan Sørvig --- src/gui/kernel/qhighdpiscaling_p.h | 21 +++++++++++++++++++++ src/gui/kernel/qwindowsysteminterface.cpp | 3 ++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h index 9e33787f53f..fac3ae420d1 100644 --- a/src/gui/kernel/qhighdpiscaling_p.h +++ b/src/gui/kernel/qhighdpiscaling_p.h @@ -47,6 +47,7 @@ #include #include +#include #include #include #include @@ -382,6 +383,24 @@ inline QRegion fromNativeLocalRegion(const QRegion &pixelRegion, const QWindow * return pointRegion; } +// When mapping expose events to Qt rects: round top/left towards the origin and +// bottom/right away from the origin, making sure that we cover the whole window. +inline QRegion fromNativeLocalExposedRegion(const QRegion &pixelRegion, const QWindow *window) +{ + if (!QHighDpiScaling::isActive()) + return pixelRegion; + + const qreal scaleFactor = QHighDpiScaling::factor(window); + QRegion pointRegion; + foreach (const QRect &rect, pixelRegion.rects()) { + const QPointF topLeftP = QPointF(rect.topLeft()) / scaleFactor; + const QPointF bottomRightP = QPointF(rect.bottomRight()) / scaleFactor; + pointRegion += QRect(QPoint(qFloor(topLeftP.x()), qFloor(topLeftP.y())), + QPoint(qCeil(bottomRightP.x()), qCeil(bottomRightP.y()))); + } + return pointRegion; +} + inline QRegion toNativeLocalRegion(const QRegion &pointRegion, const QWindow *window) { if (!QHighDpiScaling::isActive()) @@ -498,6 +517,8 @@ namespace QHighDpi { template inline T fromNativeLocalRegion(const T &value, ...) { return value; } template inline + T fromNativeLocalExposedRegion(const T &value, ...) { return value; } + template inline T toNativeLocalRegion(const T &value, ...) { return value; } template inline diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 4bbc303ac04..e10ddf22a7a 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -582,7 +582,8 @@ void QWindowSystemInterface::handleThemeChange(QWindow *tlw) void QWindowSystemInterface::handleExposeEvent(QWindow *tlw, const QRegion ®ion) { - QWindowSystemInterfacePrivate::ExposeEvent *e = new QWindowSystemInterfacePrivate::ExposeEvent(tlw, QHighDpi::fromNativeLocalRegion(region, tlw)); + QWindowSystemInterfacePrivate::ExposeEvent *e = + new QWindowSystemInterfacePrivate::ExposeEvent(tlw, QHighDpi::fromNativeLocalExposedRegion(region, tlw)); QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } From 8c2b4266002736da499d169a0da187e5cdc5381a Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 9 Feb 2016 15:51:28 +0100 Subject: [PATCH 30/62] Account for hinting preference in alpha map bounding box We would ignore the vertical hinting when calculating the bounding box, giving an off-by-one error in the base line of some characters when rendering with PreferVerticalHinting, which is the default when doing High-DPI on Windows. Task-number: QTBUG-50940 Change-Id: I2846765ec044eaf317026ee8c7bb9588257bf05c Reviewed-by: Konstantin Ritt Reviewed-by: Friedemann Kleint Reviewed-by: Alessandro Portale --- .../platforms/windows/qwindowsfontenginedirectwrite.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index bb4f4b1abdd..d99a6caecdb 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -759,12 +759,17 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph transform.m21 = matrix.m21(); transform.m22 = matrix.m22(); + DWRITE_RENDERING_MODE renderMode = + fontDef.hintingPreference == QFont::PreferNoHinting + ? DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC + : DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL; + IDWriteGlyphRunAnalysis *glyphAnalysis = NULL; HRESULT hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis( &glyphRun, 1.0f, &transform, - DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC, + renderMode, DWRITE_MEASURING_MODE_NATURAL, 0.0, 0.0, &glyphAnalysis From 5d8354e63aa37a660ac9c621276c0e87e47e0d32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simo=20F=C3=A4lt?= Date: Tue, 9 Feb 2016 12:45:44 +0200 Subject: [PATCH 31/62] Autotest: Enable make check on rhel 7.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Blacklisting all tests, which were failing locally. Task-number: QTQAINFRA-949 Change-Id: I40c25ab0155b8977596d61297ab252a546515f87 Reviewed-by: Tony Sarajärvi --- tests/auto/corelib/io/qstandardpaths/BLACKLIST | 2 ++ tests/auto/gui/kernel/qwindow/BLACKLIST | 2 ++ tests/auto/opengl/qgl/BLACKLIST | 2 ++ tests/auto/other/gestures/BLACKLIST | 2 ++ tests/auto/widgets/dialogs/qfontdialog/BLACKLIST | 1 + tests/auto/widgets/gestures/qgesturerecognizer/BLACKLIST | 6 ++++++ .../widgets/graphicsview/qgraphicsproxywidget/BLACKLIST | 3 +++ tests/auto/widgets/graphicsview/qgraphicswidget/BLACKLIST | 1 + tests/auto/widgets/kernel/qwidget/BLACKLIST | 4 ++++ tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST | 2 ++ tests/auto/widgets/widgets/qmenu/BLACKLIST | 3 +++ 11 files changed, 28 insertions(+) create mode 100644 tests/auto/corelib/io/qstandardpaths/BLACKLIST create mode 100644 tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST diff --git a/tests/auto/corelib/io/qstandardpaths/BLACKLIST b/tests/auto/corelib/io/qstandardpaths/BLACKLIST new file mode 100644 index 00000000000..8496a620b3f --- /dev/null +++ b/tests/auto/corelib/io/qstandardpaths/BLACKLIST @@ -0,0 +1,2 @@ +[testRuntimeDirectory] +rhel-7.1 diff --git a/tests/auto/gui/kernel/qwindow/BLACKLIST b/tests/auto/gui/kernel/qwindow/BLACKLIST index ee9709e68ba..26cace14035 100644 --- a/tests/auto/gui/kernel/qwindow/BLACKLIST +++ b/tests/auto/gui/kernel/qwindow/BLACKLIST @@ -1,3 +1,5 @@ +[testInputEvents] +rhel-7.1 [positioning:default] ubuntu-14.04 [modalWindowPosition] diff --git a/tests/auto/opengl/qgl/BLACKLIST b/tests/auto/opengl/qgl/BLACKLIST index fa7c829b30e..547a9a2a730 100644 --- a/tests/auto/opengl/qgl/BLACKLIST +++ b/tests/auto/opengl/qgl/BLACKLIST @@ -1,3 +1,5 @@ +[] +rhel-7.1 [glWidgetRendering] windows [glFBORendering] diff --git a/tests/auto/other/gestures/BLACKLIST b/tests/auto/other/gestures/BLACKLIST index 4e8745ca789..28e48560568 100644 --- a/tests/auto/other/gestures/BLACKLIST +++ b/tests/auto/other/gestures/BLACKLIST @@ -1,2 +1,4 @@ +[] +rhel-7.1 [customGesture] opensuse-13.1 diff --git a/tests/auto/widgets/dialogs/qfontdialog/BLACKLIST b/tests/auto/widgets/dialogs/qfontdialog/BLACKLIST index 6d3c17f35f8..ae0f7bb868a 100644 --- a/tests/auto/widgets/dialogs/qfontdialog/BLACKLIST +++ b/tests/auto/widgets/dialogs/qfontdialog/BLACKLIST @@ -1,5 +1,6 @@ [task256466_wrongStyle] opensuse-13.1 +rhel-7.1 [setFont] ubuntu-14.04 redhatenterpriselinuxworkstation-6.6 diff --git a/tests/auto/widgets/gestures/qgesturerecognizer/BLACKLIST b/tests/auto/widgets/gestures/qgesturerecognizer/BLACKLIST index 7f55c2dae02..14c41711aca 100644 --- a/tests/auto/widgets/gestures/qgesturerecognizer/BLACKLIST +++ b/tests/auto/widgets/gestures/qgesturerecognizer/BLACKLIST @@ -1,2 +1,8 @@ [panGesture:Two finger] xcb +[swipeGesture:SmallDirectionChange] +rhel-7.1 +[swipeGesture:Line] +rhel-7.1 +[pinchGesture:Standard] +rhel-7.1 diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/BLACKLIST index 717c7912806..373343fa224 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/BLACKLIST +++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/BLACKLIST @@ -1,2 +1,5 @@ [hoverEnterLeaveEvent] ubuntu-14.04 +rhel-7.1 +[QTBUG_6986_sendMouseEventToAlienWidget] +rhel-7.1 diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicswidget/BLACKLIST index 5db5c979177..c8d93585b21 100644 --- a/tests/auto/widgets/graphicsview/qgraphicswidget/BLACKLIST +++ b/tests/auto/widgets/graphicsview/qgraphicswidget/BLACKLIST @@ -1,2 +1,3 @@ [initialShow2] ubuntu-14.04 +rhel-7.1 diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST index 78ccbe302a0..8d18d40e058 100644 --- a/tests/auto/widgets/kernel/qwidget/BLACKLIST +++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST @@ -10,6 +10,7 @@ ubuntu-14.04 osx [updateWhileMinimized] ubuntu-14.04 +rhel-7.1 osx [focusProxyAndInputMethods] linux @@ -31,6 +32,7 @@ osx osx [widgetAt] osx +rhel-7.1 [sheetOpacity] osx [resizeEvent] @@ -63,8 +65,10 @@ osx osx [taskQTBUG_4055_sendSyntheticEnterLeave] osx +rhel-7.1 [syntheticEnterLeave] osx +rhel-7.1 [maskedUpdate] osx [hideWhenFocusWidgetIsChild] diff --git a/tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST b/tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST new file mode 100644 index 00000000000..a10cf663d05 --- /dev/null +++ b/tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST @@ -0,0 +1,2 @@ +[setSystemMenu] +rhel-7.1 diff --git a/tests/auto/widgets/widgets/qmenu/BLACKLIST b/tests/auto/widgets/widgets/qmenu/BLACKLIST index de49d5ff459..dbc3e268371 100644 --- a/tests/auto/widgets/widgets/qmenu/BLACKLIST +++ b/tests/auto/widgets/widgets/qmenu/BLACKLIST @@ -1,2 +1,5 @@ [task258920_mouseBorder] osx +rhel-7.1 +[pushButtonPopulateOnAboutToShow] +rhel-7.1 From 3fa7035b53a30b9aaa8566045ed157898bdcd06b Mon Sep 17 00:00:00 2001 From: Ariel Molina Date: Wed, 10 Feb 2016 14:44:53 -0600 Subject: [PATCH 32/62] Fixed bug preventing parsing of unbundled TUIO messages Unbundled TUIO messages were being ignored. TUIO protocol defaults to bundled but states it should work with any Open Sound Control (OSC) implementation. Unbundled handling was already in place, just fixed the logic to make it work. Change-Id: I6d91449bd2069ac891e493fb7f50c010bcc3e8be Reviewed-by: Robin Burchell --- src/plugins/generic/tuiotouch/qtuiohandler.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/plugins/generic/tuiotouch/qtuiohandler.cpp b/src/plugins/generic/tuiotouch/qtuiohandler.cpp index 2b42889cb1a..7ed268c2d4e 100644 --- a/src/plugins/generic/tuiotouch/qtuiohandler.cpp +++ b/src/plugins/generic/tuiotouch/qtuiohandler.cpp @@ -129,10 +129,6 @@ void QTuioHandler::processPackets() if (size != datagram.size()) datagram.resize(size); - QOscBundle bundle(datagram); - if (!bundle.isValid()) - continue; - // "A typical TUIO bundle will contain an initial ALIVE message, // followed by an arbitrary number of SET messages that can fit into the // actual bundle capacity and a concluding FSEQ message. A minimal TUIO @@ -140,7 +136,19 @@ void QTuioHandler::processPackets() // messages. The FSEQ frame ID is incremented for each delivered bundle, // while redundant bundles can be marked using the frame sequence ID // -1." - QList messages = bundle.messages(); + QList messages; + + QOscBundle bundle(datagram); + if (bundle.isValid()) { + messages = bundle.messages(); + } else { + QOscMessage msg(datagram); + if (!msg.isValid()) { + qCWarning(lcTuioSet) << "Got invalid datagram."; + continue; + } + messages.push_back(msg); + } foreach (const QOscMessage &message, messages) { if (message.addressPattern() != "/tuio/2Dcur") { From 2ee75416169ba9cda8a021b119c4c217599d03b9 Mon Sep 17 00:00:00 2001 From: Ariel Molina Date: Wed, 10 Feb 2016 12:47:29 -0600 Subject: [PATCH 33/62] Optionally force delivery of TUIO pseudo touch events TUIO is not a standard "device" as the first application takes exclusive ownership, this patch makes it deliver the events to the root window when the app is not focused, allowing for interactive application development on simulators running on the same desktop. To force delivery set the environment variable QT_TUIOTOUCH_DELIVER_WITHOUT_FOCUS to 1 Change-Id: I157f59982a1b2025ef8efdf709fe40c78339c1b4 Reviewed-by: Robin Burchell --- src/plugins/generic/tuiotouch/qtuiohandler.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/plugins/generic/tuiotouch/qtuiohandler.cpp b/src/plugins/generic/tuiotouch/qtuiohandler.cpp index 7ed268c2d4e..4b4d08441f9 100644 --- a/src/plugins/generic/tuiotouch/qtuiohandler.cpp +++ b/src/plugins/generic/tuiotouch/qtuiohandler.cpp @@ -321,6 +321,14 @@ void QTuioHandler::process2DCurFseq(const QOscMessage &message) Q_UNUSED(message); // TODO: do we need to do anything with the frame id? QWindow *win = QGuiApplication::focusWindow(); + // With TUIO the first application takes exclusive ownership of the "device" + // we cannot attach more than one application to the same port anyway. + // Forcing delivery makes it easy to use simulators in the same machine + // and forget about headaches about unfocused TUIO windows. + static bool forceDelivery = qEnvironmentVariableIsSet("QT_TUIOTOUCH_DELIVER_WITHOUT_FOCUS"); + if (!win && QGuiApplication::topLevelWindows().length() > 0 && forceDelivery) + win = QGuiApplication::topLevelWindows().at(0); + if (!win) return; From 8dc55367ca3993f465f270ef79c2cb212d821d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Mon, 8 Feb 2016 15:02:17 +0100 Subject: [PATCH 34/62] QtGui: Avoid rgba64->rgba32 conversion on every pixel in gradient Convert rgba64 color table to a new rgb32 color table only once. Use this cache when required. This patch can 2x speed up gradient painting using 32bit color format. Task-number: QTBUG-50930 Change-Id: I9212e01e397c2e0127cdf3070cc49880a2d8df88 Reviewed-by: Allan Sandfeld Jensen --- src/gui/painting/qdrawhelper.cpp | 4 +-- src/gui/painting/qdrawhelper_p.h | 9 +++--- src/gui/painting/qpaintengine_raster.cpp | 38 ++++++++++++++++++------ 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 28c7099d3c9..f0e5810b541 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -3433,13 +3433,13 @@ static SourceFetchProc64 sourceFetch64[NBlendTypes][QImage::NImageFormats] = { static uint qt_gradient_pixel_fixed(const QGradientData *data, int fixed_pos) { int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS; - return data->colorTable[qt_gradient_clamp(data, ipos)].toArgb32(); + return data->colorTable32[qt_gradient_clamp(data, ipos)]; } static const QRgba64& qt_gradient_pixel64_fixed(const QGradientData *data, int fixed_pos) { int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS; - return data->colorTable[qt_gradient_clamp(data, ipos)]; + return data->colorTable64[qt_gradient_clamp(data, ipos)]; } static void QT_FASTCALL getLinearGradientValues(LinearGradientValues *v, const QSpanData *data) diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 1ff19f4e046..ff98d186c54 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -268,7 +268,8 @@ struct QGradientData #define GRADIENT_STOPTABLE_SIZE 1024 #define GRADIENT_STOPTABLE_SIZE_SHIFT 10 - QRgba64* colorTable; //[GRADIENT_STOPTABLE_SIZE]; + const QRgba64 *colorTable64; //[GRADIENT_STOPTABLE_SIZE]; + const QRgb *colorTable32; //[GRADIENT_STOPTABLE_SIZE]; uint alphaColor : 1; }; @@ -376,13 +377,13 @@ static inline uint qt_gradient_clamp(const QGradientData *data, int ipos) static inline uint qt_gradient_pixel(const QGradientData *data, qreal pos) { int ipos = int(pos * (GRADIENT_STOPTABLE_SIZE - 1) + qreal(0.5)); - return data->colorTable[qt_gradient_clamp(data, ipos)].toArgb32(); + return data->colorTable32[qt_gradient_clamp(data, ipos)]; } static inline const QRgba64& qt_gradient_pixel64(const QGradientData *data, qreal pos) { int ipos = int(pos * (GRADIENT_STOPTABLE_SIZE - 1) + qreal(0.5)); - return data->colorTable[qt_gradient_clamp(data, ipos)]; + return data->colorTable64[qt_gradient_clamp(data, ipos)]; } static inline qreal qRadialDeterminant(qreal a, qreal b, qreal c) @@ -550,7 +551,7 @@ public: delta_det4_vec.v = Simd::v_add(delta_det4_vec.v, v_delta_delta_det16); \ b_vec.v = Simd::v_add(b_vec.v, v_delta_b4); \ for (int i = 0; i < 4; ++i) \ - *buffer++ = (extended_mask | v_buffer_mask.i[i]) & data->gradient.colorTable[index_vec.i[i]].toArgb32(); \ + *buffer++ = (extended_mask | v_buffer_mask.i[i]) & data->gradient.colorTable32[index_vec.i[i]]; \ } #define FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP) \ diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 05ccff5de00..fb44a7aeb15 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -4138,7 +4138,8 @@ class QGradientCache { inline CacheInfo(QGradientStops s, int op, QGradient::InterpolationMode mode) : stops(qMove(s)), opacity(op), interpolationMode(mode) {} - QRgba64 buffer[GRADIENT_STOPTABLE_SIZE]; + QRgba64 buffer64[GRADIENT_STOPTABLE_SIZE]; + QRgb buffer32[GRADIENT_STOPTABLE_SIZE]; QGradientStops stops; int opacity; QGradient::InterpolationMode interpolationMode; @@ -4147,7 +4148,9 @@ class QGradientCache typedef QMultiHash QGradientColorTableHash; public: - inline const QRgba64 *getBuffer(const QGradient &gradient, int opacity) { + typedef QPair ColorBufferPair; + + inline ColorBufferPair getBuffer(const QGradient &gradient, int opacity) { quint64 hash_val = 0; const QGradientStops stops = gradient.stops(); @@ -4163,7 +4166,8 @@ public: do { const CacheInfo &cache_info = it.value(); if (cache_info.stops == stops && cache_info.opacity == opacity && cache_info.interpolationMode == gradient.interpolationMode()) - return cache_info.buffer; + return qMakePair(reinterpret_cast(cache_info.buffer32), + reinterpret_cast(cache_info.buffer64)); ++it; } while (it != cache.constEnd() && it.key() == hash_val); // an exact match for these stops and opacity was not found, create new cache @@ -4177,14 +4181,18 @@ protected: inline void generateGradientColorTable(const QGradient& g, QRgba64 *colorTable, int size, int opacity) const; - QRgba64 *addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity) { + ColorBufferPair addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity) { if (cache.size() == maxCacheSize()) { // may remove more than 1, but OK cache.erase(cache.begin() + (qrand() % maxCacheSize())); } CacheInfo cache_entry(gradient.stops(), opacity, gradient.interpolationMode()); - generateGradientColorTable(gradient, cache_entry.buffer, paletteSize(), opacity); - return cache.insert(hash_val, cache_entry).value().buffer; + generateGradientColorTable(gradient, cache_entry.buffer64, paletteSize(), opacity); + for (int i = 0; i < GRADIENT_STOPTABLE_SIZE; ++i) + cache_entry.buffer32[i] = cache_entry.buffer64[i].toArgb32(); + CacheInfo &cache_value = cache.insert(hash_val, cache_entry).value(); + return qMakePair(reinterpret_cast(cache_value.buffer32), + reinterpret_cast(cache_value.buffer64)); } QGradientColorTableHash cache; @@ -4418,7 +4426,11 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode type = LinearGradient; const QLinearGradient *g = static_cast(brush.gradient()); gradient.alphaColor = !brush.isOpaque() || alpha != 256; - gradient.colorTable = const_cast(qt_gradient_cache()->getBuffer(*g, alpha)); + + QGradientCache::ColorBufferPair colorBuffers = qt_gradient_cache()->getBuffer(*g, alpha); + gradient.colorTable64 = colorBuffers.second; + gradient.colorTable32 = colorBuffers.first; + gradient.spread = g->spread(); QLinearGradientData &linearData = gradient.linear; @@ -4435,7 +4447,11 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode type = RadialGradient; const QRadialGradient *g = static_cast(brush.gradient()); gradient.alphaColor = !brush.isOpaque() || alpha != 256; - gradient.colorTable = const_cast(qt_gradient_cache()->getBuffer(*g, alpha)); + + QGradientCache::ColorBufferPair colorBuffers = qt_gradient_cache()->getBuffer(*g, alpha); + gradient.colorTable64 = colorBuffers.second; + gradient.colorTable32 = colorBuffers.first; + gradient.spread = g->spread(); QRadialGradientData &radialData = gradient.radial; @@ -4456,7 +4472,11 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode type = ConicalGradient; const QConicalGradient *g = static_cast(brush.gradient()); gradient.alphaColor = !brush.isOpaque() || alpha != 256; - gradient.colorTable = const_cast(qt_gradient_cache()->getBuffer(*g, alpha)); + + QGradientCache::ColorBufferPair colorBuffers = qt_gradient_cache()->getBuffer(*g, alpha); + gradient.colorTable64 = colorBuffers.second; + gradient.colorTable32 = colorBuffers.first; + gradient.spread = QGradient::RepeatSpread; QConicalGradientData &conicalData = gradient.conical; From 448e9fdb57f6a7f7c2ad3986231039f21b20f854 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 2 Feb 2016 12:57:21 +0100 Subject: [PATCH 35/62] Enable NRVO in QJsonObject::keys() ... for poor compilers (such as GCC). The test (!d) was changed to match what other member functions test for, e.g. toVariantHash(). Change-Id: I85aee0df6e50da3623ad0afce24abb586e0bd1bc Reviewed-by: Lars Knoll --- src/corelib/json/qjsonobject.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp index 27f937e7506..e43d8111570 100644 --- a/src/corelib/json/qjsonobject.cpp +++ b/src/corelib/json/qjsonobject.cpp @@ -270,16 +270,14 @@ QVariantHash QJsonObject::toVariantHash() const */ QStringList QJsonObject::keys() const { - if (!d) - return QStringList(); - QStringList keys; - keys.reserve(o->length); - for (uint i = 0; i < o->length; ++i) { - QJsonPrivate::Entry *e = o->entryAt(i); - keys.append(e->key()); + if (o) { + keys.reserve(o->length); + for (uint i = 0; i < o->length; ++i) { + QJsonPrivate::Entry *e = o->entryAt(i); + keys.append(e->key()); + } } - return keys; } From 3cf4c492c2f8cf9f13f9e171b2f3fa6cbb2303f9 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Fri, 29 Jan 2016 16:07:24 +0100 Subject: [PATCH 36/62] Document QWinOverlappedIoNotifier restrictions Change-Id: I13cd14c29ddaf4c7423d672b0551081f87d8726b Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qwinoverlappedionotifier.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/corelib/io/qwinoverlappedionotifier.cpp b/src/corelib/io/qwinoverlappedionotifier.cpp index 0cefa374fa8..dee263c664c 100644 --- a/src/corelib/io/qwinoverlappedionotifier.cpp +++ b/src/corelib/io/qwinoverlappedionotifier.cpp @@ -75,6 +75,22 @@ QT_BEGIN_NAMESPACE or WriteFile() is ignored and can be used for other purposes. \warning This class is only available on Windows. + + Due to peculiarities of the Windows I/O completion port API, users of + QWinOverlappedIoNotifier must pay attention to the following restrictions: + \list + \li File handles with a QWinOverlappedIoNotifer are assigned to an I/O + completion port until the handle is closed. It is impossible to + disassociate the file handle from the I/O completion port. + \li There can be only one QWinOverlappedIoNotifer per file handle. Creating + another QWinOverlappedIoNotifier for that file, even with a duplicated + handle, will fail. + \li Certain Windows API functions are unavailable for file handles that are + assigned to an I/O completion port. This includes the functions + \c{ReadFileEx} and \c{WriteFileEx}. + \endlist + See also the remarks in the MSDN documentation for the + \c{CreateIoCompletionPort} function. */ struct IOResult From 707068bd663c68e8d4716dbb46d1fcca13c6dcf2 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 9 Apr 2015 16:21:37 +0200 Subject: [PATCH 37/62] Remove Windows CE build hacks from QWindowsPipeWriter Those were added in ancient times to make QWindowsPipeWriter compile on Windows CE. It was never used though. Change-Id: Ica71b182f7ee4e47d9e33638d78475842b2ecdff Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qwindowspipewriter.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index fd14523d456..21df5d06434 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -43,13 +43,8 @@ QWindowsPipeWriter::QWindowsPipeWriter(HANDLE pipe, QObject * parent) quitNow(false), hasWritten(false) { -#if !defined(Q_OS_WINCE) || (_WIN32_WCE >= 0x600) DuplicateHandle(GetCurrentProcess(), pipe, GetCurrentProcess(), &writePipe, 0, FALSE, DUPLICATE_SAME_ACCESS); -#else - Q_UNUSED(pipe); - writePipe = GetCurrentProcess(); -#endif } QWindowsPipeWriter::~QWindowsPipeWriter() @@ -60,9 +55,7 @@ QWindowsPipeWriter::~QWindowsPipeWriter() lock.unlock(); if (!wait(30000)) terminate(); -#if !defined(Q_OS_WINCE) || (_WIN32_WCE >= 0x600) CloseHandle(writePipe); -#endif } bool QWindowsPipeWriter::waitForWrite(int msecs) @@ -153,7 +146,6 @@ void QWindowsPipeWriter::run() msleep(100); continue; } -#ifndef Q_OS_WINCE if (writeError != ERROR_IO_PENDING) { qErrnoWarning(writeError, "QWindowsPipeWriter: async WriteFile failed."); return; @@ -162,9 +154,6 @@ void QWindowsPipeWriter::run() qErrnoWarning(GetLastError(), "QWindowsPipeWriter: GetOverlappedResult failed."); return; } -#else - return; -#endif } totalWritten += written; #if defined QPIPEWRITER_DEBUG From 70fb36e4bdefa37cff77decac5d549368e805aa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Martins?= Date: Sun, 7 Feb 2016 01:39:37 +0000 Subject: [PATCH 38/62] docs: State that QMap::equal_range() returns an open-ended interval Change-Id: If31dd078aeb92e479db8c1f0a5e58e56b549b5f6 Reviewed-by: Martin Smith Reviewed-by: Marc Mutz --- src/corelib/tools/qmap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp index e49a1a098d6..27ae07441e3 100644 --- a/src/corelib/tools/qmap.cpp +++ b/src/corelib/tools/qmap.cpp @@ -1175,7 +1175,7 @@ void QMapDataBase::freeData(QMapDataBase *d) /*! \fn QPair QMap::equal_range(const Key &key) - Returns a pair of iterators delimiting the range of values that + Returns a pair of iterators delimiting the range of values \c{[first, second)}, that are stored under \a key. */ From 62984d89187b2a65137db3029235d358dd3c703a Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 9 Feb 2016 12:14:21 +0100 Subject: [PATCH 39/62] Fix input pane usage on Windows 10 IoT Core Running on Raspberry Pi casting to IInputPane2 fails with E_NO_INTERFACE as there is no input pane available for the device. However, if E_NO_INTERFACE is returned from the lambda, then deletion of the ComPtr holding the AsyncAction in runOnXamlThread() crashes somewhere deep internally of Release(). As we do not check for the return value anywhere, avoid the crash by returning S_OK instead. Change-Id: Icd38ec482b365285a482e5ff792ec1b4f13317d5 Reviewed-by: Andrew Knight Reviewed-by: Laszlo Agocs --- src/plugins/platforms/winrt/qwinrtinputcontext.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp index a0474b6710c..9228ef8d622 100644 --- a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp +++ b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp @@ -169,12 +169,12 @@ void QWinRTInputContext::showInputPanel() ComPtr inputPane; HRESULT hr = getInputPane(&inputPane); if (FAILED(hr)) - return hr; + return S_OK; boolean success; hr = inputPane->TryShow(&success); if (FAILED(hr) || !success) qErrnoWarning(hr, "Failed to show input panel."); - return hr; + return S_OK; }); } @@ -184,12 +184,12 @@ void QWinRTInputContext::hideInputPanel() ComPtr inputPane; HRESULT hr = getInputPane(&inputPane); if (FAILED(hr)) - return hr; + return S_OK; boolean success; hr = inputPane->TryHide(&success); if (FAILED(hr) || !success) qErrnoWarning(hr, "Failed to hide input panel."); - return hr; + return S_OK; }); } From 966e893151952d19131f21738861c483b8af042c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 8 Feb 2016 15:51:46 +0100 Subject: [PATCH 40/62] Windows QPA: Prefer const-versions of API where applicable. Ensure no detaching occurs by using Container::constFirst() and QImage::constScanLine(). Change-Id: Ie197d795d9329de8be76ed388ba2c71ccf201f5c Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowscursor.cpp | 8 ++++---- src/plugins/platforms/windows/qwindowseglcontext.cpp | 2 +- src/plugins/platforms/windows/qwindowsfontengine.cpp | 6 +++--- .../platforms/windows/qwindowsfontenginedirectwrite.cpp | 2 +- src/plugins/platforms/windows/qwindowsmime.cpp | 4 ++-- src/plugins/platforms/windows/qwindowswindow.cpp | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index b9e893c6503..9f65f73a812 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -142,8 +142,8 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits, QScopedArrayPointer xMask(new uchar[height * n]); int x = 0; for (int i = 0; i < height; ++i) { - const uchar *bits = bbits.scanLine(i); - const uchar *mask = mbits.scanLine(i); + const uchar *bits = bbits.constScanLine(i); + const uchar *mask = mbits.constScanLine(i); for (int j = 0; j < n; ++j) { uchar b = bits[j]; uchar m = mask[j]; @@ -173,8 +173,8 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits, x += sysN; } else { int fillWidth = n > sysN ? sysN : n; - const uchar *bits = bbits.scanLine(i); - const uchar *mask = mbits.scanLine(i); + const uchar *bits = bbits.constScanLine(i); + const uchar *mask = mbits.constScanLine(i); for (int j = 0; j < fillWidth; ++j) { uchar b = bits[j]; uchar m = mask[j]; diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 20517bc5a91..59837417111 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -990,7 +990,7 @@ EGLConfig QWindowsEGLContext::chooseConfig(const QSurfaceFormat &format) QVector configs(matching); QWindowsEGLStaticContext::libEGL.eglChooseConfig(display, configureAttributes.constData(), configs.data(), configs.size(), &matching); if (!cfg && matching > 0) - cfg = configs.first(); + cfg = configs.constFirst(); EGLint red = 0; EGLint green = 0; diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp index 4f463dd77ca..00f9ecea602 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.cpp +++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp @@ -1174,11 +1174,11 @@ QImage QWindowsFontEngine::alphaMapForGlyph(glyph_t glyph, const QTransform &xfo for (int y=0; yheight(); ++y) { uchar *dest = alphaMap.scanLine(y); if (mask->image().format() == QImage::Format_RGB16) { - const qint16 *src = (qint16 *) ((const QImage &) mask->image()).scanLine(y); + const qint16 *src = reinterpret_cast(mask->image().constScanLine(y)); for (int x=0; xwidth(); ++x) dest[x] = 255 - qGray(src[x]); } else { - const uint *src = (uint *) ((const QImage &) mask->image()).scanLine(y); + const uint *src = reinterpret_cast(mask->image().constScanLine(y)); for (int x=0; xwidth(); ++x) { if (QWindowsNativeImage::systemFormat() == QImage::Format_RGB16) dest[x] = 255 - qGray(src[x]); @@ -1223,7 +1223,7 @@ QImage QWindowsFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed, const QTra QImage rgbMask(mask->width(), mask->height(), QImage::Format_RGB32); for (int y=0; yheight(); ++y) { uint *dest = (uint *) rgbMask.scanLine(y); - const uint *src = (uint *) source.scanLine(y); + const uint *src = reinterpret_cast(source.constScanLine(y)); for (int x=0; xwidth(); ++x) { dest[x] = 0xffffffff - (0x00ffffff & src[x]); } diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index bb4f4b1abdd..71491595a49 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -493,7 +493,7 @@ QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed sub QImage alphaMap(im.width(), im.height(), QImage::Format_Alpha8); for (int y=0; y(im.constScanLine(y)); uchar *dst = alphaMap.scanLine(y); for (int x=0; xpow_gamma[qGray(0xffffffff - *src)] * 255. / 2047.); diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index eaaf2820ee8..a8264b55c00 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -175,8 +175,8 @@ static bool qt_write_dibv5(QDataStream &s, QImage image) memset(buf, 0, bpl_bmp); for (int y=image.height()-1; y>=0; y--) { // write the image bits - QRgb *p = (QRgb *)image.scanLine(y); - QRgb *end = p + image.width(); + const QRgb *p = reinterpret_cast(image.constScanLine(y)); + const QRgb *end = p + image.width(); b = buf; while (p < end) { int alpha = qAlpha(*p); diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 82d67e36f5e..2ff71d827b3 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -183,7 +183,7 @@ static QPoint windowPlacementOffset(HWND hwnd, const QPoint &point) return QPoint(0, 0); const QWindowsScreenManager &screenManager = QWindowsContext::instance()->screenManager(); const QWindowsScreen *screen = screenManager.screens().size() == 1 - ? screenManager.screens().first() : screenManager.screenAtDp(point); + ? screenManager.screens().constFirst() : screenManager.screenAtDp(point); if (screen) return screen->availableGeometry().topLeft() - screen->geometry().topLeft(); #else From 9915630d0886434e8984904b1cadedc81dc78ca0 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 6 Jan 2016 16:10:11 +0100 Subject: [PATCH 41/62] QPlatformWindow::screenForGeometry(): Use mapToGlobal(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QPlatformWindow::mapToGlobal() should be used to obtain global coordinates for foreign/embedded windows. They do not have a parent QWindow, but the geometry passed in might be local to their native parent window. For normal top-level windows, this is a no-op. Task-number: QTBUG-50206 Task-number: QTBUG-41186 Change-Id: I00889b28db69ae65057f48b9e74bd4d8cfffa136 Reviewed-by: Tor Arne Vestbø --- src/gui/kernel/qplatformwindow.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp index aea029b7f5c..04532e82aaf 100644 --- a/src/gui/kernel/qplatformwindow.cpp +++ b/src/gui/kernel/qplatformwindow.cpp @@ -484,8 +484,10 @@ QPlatformScreen *QPlatformWindow::screenForGeometry(const QRect &newGeometry) co { QPlatformScreen *currentScreen = screen(); QPlatformScreen *fallback = currentScreen; - //QRect::center can return a value outside the rectangle if it's empty - const QPoint center = newGeometry.isEmpty() ? newGeometry.topLeft() : newGeometry.center(); + // QRect::center can return a value outside the rectangle if it's empty. + // Apply mapToGlobal() in case it is a foreign/embedded window. + const QPoint center = + mapToGlobal(newGeometry.isEmpty() ? newGeometry.topLeft() : newGeometry.center()); if (!parent() && currentScreen && !currentScreen->geometry().contains(center)) { Q_FOREACH (QPlatformScreen* screen, currentScreen->virtualSiblings()) { From ac8a3b948da1980bc59bae3fc76d20b5b45662a0 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 9 Feb 2016 09:14:12 +0100 Subject: [PATCH 42/62] QtGui: Use QImage::constBits()/constScanLine() in non-const contexts. Prevent potential detaching by using constBits()/constScanLine() instead of bits()/scanLine(). Change-Id: If03f8d4d3b8ed4c07aed5eff7f580e57ca771919 Reviewed-by: Gunnar Sletta Reviewed-by: Marc Mutz --- src/gui/image/qgifhandler.cpp | 4 ++-- src/gui/image/qpixmap_blitter.cpp | 2 +- src/gui/image/qpixmap_win.cpp | 2 +- src/gui/image/qppmhandler.cpp | 6 +++--- src/gui/image/qxbmhandler.cpp | 2 +- src/gui/image/qxpmhandler.cpp | 4 ++-- src/gui/painting/qpaintengine_raster.cpp | 4 ++-- src/gui/painting/qregion.cpp | 4 ++-- src/gui/painting/qtextureglyphcache.cpp | 6 +++--- src/gui/text/qfontengine.cpp | 8 ++++---- 10 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/gui/image/qgifhandler.cpp b/src/gui/image/qgifhandler.cpp index 7ba6b123e8a..9c748c03734 100644 --- a/src/gui/image/qgifhandler.cpp +++ b/src/gui/image/qgifhandler.cpp @@ -199,7 +199,7 @@ void QGIFFormat::disposePrevious(QImage *image) fillRect(image, l, t, r-l+1, b-t+1, color(bgcol)); } else { // Impossible: We don't know of a bgcol - use pixel 0 - QRgb *bits = (QRgb*)image->bits(); + const QRgb *bits = reinterpret_cast(image->constBits()); fillRect(image, l, t, r-l+1, b-t+1, bits[0]); } // ### Changed: QRect(l, t, r-l+1, b-t+1) @@ -208,7 +208,7 @@ void QGIFFormat::disposePrevious(QImage *image) if (frame >= 0) { for (int ln=t; ln<=b; ln++) { memcpy(image->scanLine(ln)+l, - backingstore.scanLine(ln-t), + backingstore.constScanLine(ln-t), (r-l+1)*sizeof(QRgb)); } // ### Changed: QRect(l, t, r-l+1, b-t+1) diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp index b254c5a2af2..a68425e1006 100644 --- a/src/gui/image/qpixmap_blitter.cpp +++ b/src/gui/image/qpixmap_blitter.cpp @@ -183,7 +183,7 @@ void QBlittablePlatformPixmap::fromImage(const QImage &image, correctFormatPic = correctFormatPic.convertToFormat(thisImg->format(), flags); uchar *mem = thisImg->bits(); - const uchar *bits = correctFormatPic.bits(); + const uchar *bits = correctFormatPic.constBits(); int bytesCopied = 0; while (bytesCopied < correctFormatPic.byteCount()) { memcpy(mem,bits,correctFormatPic.bytesPerLine()); diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp index a7a9b375ff4..8db3bdbc7f3 100644 --- a/src/gui/image/qpixmap_win.cpp +++ b/src/gui/image/qpixmap_win.cpp @@ -198,7 +198,7 @@ Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap) QScopedArrayPointer bits(new uchar[bpl * h]); bm.invertPixels(); for (int y = 0; y < h; ++y) - memcpy(bits.data() + y * bpl, bm.scanLine(y), bpl); + memcpy(bits.data() + y * bpl, bm.constScanLine(y), bpl); HBITMAP hbm = CreateBitmap(w, h, 1, 1, bits.data()); return hbm; } diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp index 7f23656c02e..6eb35e15586 100644 --- a/src/gui/image/qppmhandler.cpp +++ b/src/gui/image/qppmhandler.cpp @@ -329,7 +329,7 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QBy if (image.format() == QImage::Format_Indexed8) { QVector color = image.colorTable(); for (uint y=0; y(image.constScanLine(y)); uchar *p = buf; uchar *end = buf+bpl; while (p < end) { diff --git a/src/gui/image/qxbmhandler.cpp b/src/gui/image/qxbmhandler.cpp index 81525d9dd6e..44d07f1624e 100644 --- a/src/gui/image/qxbmhandler.cpp +++ b/src/gui/image/qxbmhandler.cpp @@ -210,7 +210,7 @@ static bool write_xbm_image(const QImage &sourceImage, QIODevice *device, const char *p = buf; int bpl = (w+7)/8; for (int y = 0; y < h; ++y) { - uchar *b = image.scanLine(y); + const uchar *b = image.constScanLine(y); for (i = 0; i < bpl; ++i) { *p++ = '0'; *p++ = 'x'; *p++ = hexrep[*b >> 4]; diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp index e9ac4a9cc29..fbce78eb748 100644 --- a/src/gui/image/qxpmhandler.cpp +++ b/src/gui/image/qxpmhandler.cpp @@ -1098,7 +1098,7 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const // build color table for(y=0; y(image.constScanLine(y)); for(x=0; x(image.constScanLine(y)); int cc = 0; for(x=0; x(dest.scanLine(y)); if (!source || !target) QT_THROW(std::bad_alloc()); // we must have run out of memory diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp index 5e648eabf53..757c78cec8e 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -3735,7 +3735,7 @@ static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule) QRegionPrivate *qt_bitmapToRegion(const QBitmap& bitmap) { - QImage image = bitmap.toImage(); + const QImage image = bitmap.toImage(); QRegionPrivate *region = new QRegionPrivate; @@ -3753,7 +3753,7 @@ QRegionPrivate *qt_bitmapToRegion(const QBitmap& bitmap) int x, y; for (y = 0; y < image.height(); ++y) { - uchar *line = image.scanLine(y); + const uchar *line = image.constScanLine(y); int w = image.width(); uchar all = zero; int prev1 = -1; diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index 97f82d16d39..20039d902a2 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -339,7 +339,7 @@ void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subP uchar *dest = d + (c.y + y) *dbpl + c.x/8; if (y < mh) { - uchar *src = mask.scanLine(y); + const uchar *src = mask.constScanLine(y); for (int x = 0; x < c.w/8; ++x) { if (x < (mw+7)/8) dest[x] = src[x]; @@ -361,7 +361,7 @@ void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subP for (int y = 0; y < c.h; ++y) { uchar *dest = d + (c.y + y) *dbpl + c.x; if (y < mh) { - uchar *src = (uchar *) mask.scanLine(y); + const uchar *src = mask.constScanLine(y); for (int x = 0; x < c.w; ++x) { if (x < mw) dest[x] = (src[x >> 3] & (1 << (7 - (x & 7)))) > 0 ? 255 : 0; @@ -372,7 +372,7 @@ void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subP for (int y = 0; y < c.h; ++y) { uchar *dest = d + (c.y + y) *dbpl + c.x; if (y < mh) { - uchar *src = (uchar *) mask.scanLine(y); + const uchar *src = mask.constScanLine(y); for (int x = 0; x < c.w; ++x) { if (x < mw) dest[x] = src[x]; diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index fc66c4ec4cb..03ad6a24e97 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -823,7 +823,7 @@ void QFontEngine::addBitmapFontToPath(qreal x, qreal y, const QGlyphLayout &glyp } } } - const uchar *bitmap_data = bitmap.bits(); + const uchar *bitmap_data = bitmap.constBits(); QFixedPoint offset = glyphs.offsets[i]; advanceX += offset.x; advanceY += offset.y; @@ -880,12 +880,12 @@ QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, con QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed /*subPixelPosition*/, const QTransform &t) { - QImage alphaMask = alphaMapForGlyph(glyph, t); + const QImage alphaMask = alphaMapForGlyph(glyph, t); QImage rgbMask(alphaMask.width(), alphaMask.height(), QImage::Format_RGB32); for (int y=0; y(im.constScanLine(y)); for (int x=0; x Date: Fri, 12 Feb 2016 12:37:15 +0100 Subject: [PATCH 43/62] Search for libsystemd first, fall back to libsystemd-journal systemd >= 209 merged the individual libraries libsystemd-journal, libsystemd-login, libsystemd-id128 and libsystemd-daemon into a single library, libsystemd. To ease the transition one could pass an option to its build to generate stub libraries and matching pkg-config files. With systemd >= 229 this option has now been removed, causing the build to fail when the journald option is enabled. Change-Id: I26670f207f1a9e79c16be5ce8c8a49353143c5ba Reviewed-by: Oswald Buddenhagen Reviewed-by: Robin Burchell --- config.tests/unix/journald/journald.pro | 6 +++++- src/corelib/global/global.pri | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/config.tests/unix/journald/journald.pro b/config.tests/unix/journald/journald.pro index 2bb50ceb71c..ea765642e6e 100644 --- a/config.tests/unix/journald/journald.pro +++ b/config.tests/unix/journald/journald.pro @@ -1,6 +1,10 @@ SOURCES = journald.c CONFIG += link_pkgconfig -PKGCONFIG_PRIVATE += libsystemd-journal + +packagesExist(libsystemd): \ + PKGCONFIG_PRIVATE += libsystemd +else: \ + PKGCONFIG_PRIVATE += libsystemd-journal CONFIG -= qt diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index aa4945f90e3..dd846955f61 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -53,7 +53,10 @@ slog2 { journald { CONFIG += link_pkgconfig - PKGCONFIG_PRIVATE += libsystemd-journal + packagesExist(libsystemd): \ + PKGCONFIG_PRIVATE += libsystemd + else: \ + PKGCONFIG_PRIVATE += libsystemd-journal DEFINES += QT_USE_JOURNALD } From 018e670a26ff5a61b949100ae080f5e654e7bee8 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Mon, 4 Jan 2016 17:56:05 +0100 Subject: [PATCH 44/62] OS X: Implement download folder display name query Up to now, the download folder display name was queried using FSFindFolder and kDesktopFolderType. Now that NSFileManager can be used unconditionnaly, the query has been replaced to use NSFileManager. [ChangeLog][QtCore][OS X] QStandardPaths now returns the correct display name for the download folder. Task-number: QTBUG-50262 Change-Id: Ie16c8daea3261a4dd5ca051956fc08d51656e0fa Reviewed-by: Jake Petroules --- src/corelib/io/qstandardpaths_mac.mm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/corelib/io/qstandardpaths_mac.mm b/src/corelib/io/qstandardpaths_mac.mm index 7b97a03db2d..f65ca2048a6 100644 --- a/src/corelib/io/qstandardpaths_mac.mm +++ b/src/corelib/io/qstandardpaths_mac.mm @@ -229,6 +229,14 @@ QString QStandardPaths::displayName(StandardLocation type) if (QStandardPaths::HomeLocation == type) return QCoreApplication::translate("QStandardPaths", "Home"); + if (QStandardPaths::DownloadLocation == type) { + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSURL *url = [fileManager URLForDirectory:NSDownloadsDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil]; + if (!url) + return QString(); + return QString::fromNSString([fileManager displayNameAtPath: [url absoluteString]]); + } + FSRef ref; OSErr err = FSFindFolder(kOnAppropriateDisk, translateLocation(type), false, &ref); if (err) From 58141642b6e20fc0ad5f32158d6ace05017be49a Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Fri, 5 Feb 2016 23:39:36 +0100 Subject: [PATCH 45/62] Doc: Fixed Qt::TextWordBreak to Qt::TextWordWrap Change-Id: I0c50eab22c7ffaa7f39111b37979b92fd5c7f35f Reviewed-by: Sze Howe Koh --- src/gui/text/qfontmetrics.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp index 5bc9fe3c7fe..32e40b9f4d1 100644 --- a/src/gui/text/qfontmetrics.cpp +++ b/src/gui/text/qfontmetrics.cpp @@ -789,7 +789,7 @@ QRect QFontMetrics::boundingRect(const QRect &rect, int flags, const QString &te \li Qt::TextSingleLine ignores newline characters. \li Qt::TextExpandTabs expands tabs (see below) \li Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined. - \li Qt::TextWordBreak breaks the text to fit the rectangle. + \li Qt::TextWordWrap breaks the text to fit the rectangle. \endlist If Qt::TextExpandTabs is set in \a flags, then: if \a tabArray is @@ -1573,7 +1573,7 @@ QRectF QFontMetricsF::boundingRect(const QRectF &rect, int flags, const QString& \li Qt::TextSingleLine ignores newline characters. \li Qt::TextExpandTabs expands tabs (see below) \li Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined. - \li Qt::TextWordBreak breaks the text to fit the rectangle. + \li Qt::TextWordWrap breaks the text to fit the rectangle. \endlist These flags are defined in the \l{Qt::TextFlag} enum. From bfb47b39f6f72bf61b457ed54e8c259fb472fa99 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 12 Feb 2016 11:08:40 +0100 Subject: [PATCH 46/62] Windows QPA: Fix the signature of the font enumeration callbacks. Instead of casting the function in the calls to EnumFontFamiliesEx(), use the correct signature and cast inside the callbacks. Also avoid unconditionally casting the TEXTMETRIC parameter to NEWTEXTMETRICEX since according to documentation NEWTEXTMETRICEX is passed for TrueType fonts only. Task-number: QTBUG-50804 Change-Id: I0393474ac06000fc3f12d2dbc2a5aa37a6b44849 Reviewed-by: Konstantin Ritt Reviewed-by: Oliver Wolff --- .../windows/qwindowsfontdatabase.cpp | 42 ++++++++++-------- .../windows/qwindowsfontdatabase_ft.cpp | 43 ++++++++++--------- 2 files changed, 46 insertions(+), 39 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index bf42ca190b8..1adf4115c9b 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -870,14 +870,13 @@ static bool addFontToDatabase(const QString &familyName, uchar charSet, static const int SMOOTH_SCALABLE = 0xffff; const QString foundryName; // No such concept. - const NEWTEXTMETRIC *tm = (NEWTEXTMETRIC *)textmetric; - const bool fixed = !(tm->tmPitchAndFamily & TMPF_FIXED_PITCH); - const bool ttf = (tm->tmPitchAndFamily & TMPF_TRUETYPE); - const bool scalable = tm->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE); - const int size = scalable ? SMOOTH_SCALABLE : tm->tmHeight; - const QFont::Style style = tm->tmItalic ? QFont::StyleItalic : QFont::StyleNormal; + const bool fixed = !(textmetric->tmPitchAndFamily & TMPF_FIXED_PITCH); + const bool ttf = (textmetric->tmPitchAndFamily & TMPF_TRUETYPE); + const bool scalable = textmetric->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE); + const int size = scalable ? SMOOTH_SCALABLE : textmetric->tmHeight; + const QFont::Style style = textmetric->tmItalic ? QFont::StyleItalic : QFont::StyleNormal; const bool antialias = false; - const QFont::Weight weight = QPlatformFontDatabase::weightFromInteger(tm->tmWeight); + const QFont::Weight weight = QPlatformFontDatabase::weightFromInteger(textmetric->tmWeight); const QFont::Stretch stretch = QFont::Unstretched; #ifndef QT_NO_DEBUG_OUTPUT @@ -957,18 +956,21 @@ static bool addFontToDatabase(const QString &familyName, uchar charSet, return true; } -static int QT_WIN_CALLBACK storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric, - int type, LPARAM registerAlias) +static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *textmetric, + DWORD type, LPARAM lParam) { + const ENUMLOGFONTEX *f = reinterpret_cast(logFont); const QString familyName = QString::fromWCharArray(f->elfLogFont.lfFaceName); const uchar charSet = f->elfLogFont.lfCharSet; + const bool registerAlias = bool(lParam); - const FONTSIGNATURE signature = textmetric->ntmFontSig; - - // NEWTEXTMETRICEX is a NEWTEXTMETRIC, which according to the documentation is - // identical to a TEXTMETRIC except for the last four members, which we don't use - // anyway - addFontToDatabase(familyName, charSet, (TEXTMETRIC *)textmetric, &signature, type, registerAlias); + // NEWTEXTMETRICEX (passed for TT fonts) is a NEWTEXTMETRIC, which according + // to the documentation is identical to a TEXTMETRIC except for the last four + // members, which we don't use anyway + const FONTSIGNATURE *signature = Q_NULLPTR; + if (type & TRUETYPE_FONTTYPE) + signature = &reinterpret_cast(textmetric)->ntmFontSig; + addFontToDatabase(familyName, charSet, textmetric, signature, type, registerAlias); // keep on enumerating return 1; @@ -987,7 +989,7 @@ void QWindowsFontDatabase::populateFamily(const QString &familyName, bool regist familyName.toWCharArray(lf.lfFaceName); lf.lfFaceName[familyName.size()] = 0; lf.lfPitchAndFamily = 0; - EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont, (LPARAM)registerAlias, 0); + EnumFontFamiliesEx(dummy, &lf, storeFont, LPARAM(registerAlias), 0); ReleaseDC(0, dummy); } @@ -1008,9 +1010,11 @@ struct PopulateFamiliesContext }; } // namespace -static int QT_WIN_CALLBACK populateFontFamilies(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *tm, int, LPARAM lparam) +static int QT_WIN_CALLBACK populateFontFamilies(const LOGFONT *logFont, const TEXTMETRIC *textmetric, + DWORD, LPARAM lparam) { // the "@family" fonts are just the same as "family". Ignore them. + const ENUMLOGFONTEX *f = reinterpret_cast(logFont); const wchar_t *faceNameW = f->elfLogFont.lfFaceName; if (faceNameW[0] && faceNameW[0] != L'@' && wcsncmp(faceNameW, L"WST_", 4)) { const QString faceName = QString::fromWCharArray(faceNameW); @@ -1020,7 +1024,7 @@ static int QT_WIN_CALLBACK populateFontFamilies(ENUMLOGFONTEX* f, NEWTEXTMETRICE context->seenSystemDefaultFont = true; // Register current font's english name as alias - const bool ttf = (tm->ntmTm.tmPitchAndFamily & TMPF_TRUETYPE); + const bool ttf = textmetric->tmPitchAndFamily & TMPF_TRUETYPE; if (ttf && localizedName(faceName)) { const QString englishName = getEnglishName(faceName); if (!englishName.isEmpty()) { @@ -1044,7 +1048,7 @@ void QWindowsFontDatabase::populateFontDatabase() lf.lfFaceName[0] = 0; lf.lfPitchAndFamily = 0; PopulateFamiliesContext context(QWindowsFontDatabase::systemDefaultFont().family()); - EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)populateFontFamilies, reinterpret_cast(&context), 0); + EnumFontFamiliesEx(dummy, &lf, populateFontFamilies, reinterpret_cast(&context), 0); ReleaseDC(0, dummy); // Work around EnumFontFamiliesEx() not listing the system font. if (!context.seenSystemDefaultFont) diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp index 88ceb37693f..823c3e7c7b9 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp @@ -392,14 +392,13 @@ static bool addFontToDatabase(const QString &faceName, static const int SMOOTH_SCALABLE = 0xffff; const QString foundryName; // No such concept. - const NEWTEXTMETRIC *tm = (NEWTEXTMETRIC *)textmetric; - const bool fixed = !(tm->tmPitchAndFamily & TMPF_FIXED_PITCH); - const bool ttf = (tm->tmPitchAndFamily & TMPF_TRUETYPE); - const bool scalable = tm->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE); - const int size = scalable ? SMOOTH_SCALABLE : tm->tmHeight; - const QFont::Style style = tm->tmItalic ? QFont::StyleItalic : QFont::StyleNormal; + const bool fixed = !(textmetric->tmPitchAndFamily & TMPF_FIXED_PITCH); + const bool ttf = (textmetric->tmPitchAndFamily & TMPF_TRUETYPE); + const bool scalable = textmetric->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE); + const int size = scalable ? SMOOTH_SCALABLE : textmetric->tmHeight; + const QFont::Style style = textmetric->tmItalic ? QFont::StyleItalic : QFont::StyleNormal; const bool antialias = false; - const QFont::Weight weight = QPlatformFontDatabase::weightFromInteger(tm->tmWeight); + const QFont::Weight weight = QPlatformFontDatabase::weightFromInteger(textmetric->tmWeight); const QFont::Stretch stretch = QFont::Unstretched; #ifndef QT_NO_DEBUG_STREAM @@ -516,19 +515,21 @@ static QByteArray getFntTable(HFONT hfont, uint tag) } #endif -static int QT_WIN_CALLBACK storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric, - int type, LPARAM) +static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *textmetric, + DWORD type, LPARAM) { - + const ENUMLOGFONTEX *f = reinterpret_cast(logFont); const QString faceName = QString::fromWCharArray(f->elfLogFont.lfFaceName); const QString fullName = QString::fromWCharArray(f->elfFullName); const uchar charSet = f->elfLogFont.lfCharSet; - const FONTSIGNATURE signature = textmetric->ntmFontSig; - // NEWTEXTMETRICEX is a NEWTEXTMETRIC, which according to the documentation is - // identical to a TEXTMETRIC except for the last four members, which we don't use - // anyway - addFontToDatabase(faceName, fullName, charSet, (TEXTMETRIC *)textmetric, &signature, type, false); + // NEWTEXTMETRICEX (passed for TT fonts) is a NEWTEXTMETRIC, which according + // to the documentation is identical to a TEXTMETRIC except for the last four + // members, which we don't use anyway + const FONTSIGNATURE *signature = Q_NULLPTR; + if (type & TRUETYPE_FONTTYPE) + signature = &reinterpret_cast(textmetric)->ntmFontSig; + addFontToDatabase(faceName, fullName, charSet, textmetric, signature, type, false); // keep on enumerating return 1; @@ -555,7 +556,7 @@ void QWindowsFontDatabaseFT::populateFamily(const QString &familyName) familyName.toWCharArray(lf.lfFaceName); lf.lfFaceName[familyName.size()] = 0; lf.lfPitchAndFamily = 0; - EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont, 0, 0); + EnumFontFamiliesEx(dummy, &lf, storeFont, 0, 0); ReleaseDC(0, dummy); } @@ -575,17 +576,20 @@ struct PopulateFamiliesContext // Delayed population of font families -static int QT_WIN_CALLBACK populateFontFamilies(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *tm, int, LPARAM lparam) +static int QT_WIN_CALLBACK populateFontFamilies(const LOGFONT *logFont, const TEXTMETRIC *textmetric, + DWORD, LPARAM lparam) { + const ENUMLOGFONTEX *f = reinterpret_cast(logFont); // the "@family" fonts are just the same as "family". Ignore them. const wchar_t *faceNameW = f->elfLogFont.lfFaceName; if (faceNameW[0] && faceNameW[0] != L'@' && wcsncmp(faceNameW, L"WST_", 4)) { // Register only font families for which a font file exists for delayed population + const bool ttf = textmetric->tmPitchAndFamily & TMPF_TRUETYPE; const QString faceName = QString::fromWCharArray(faceNameW); const FontKey *key = findFontKey(faceName); if (!key) { key = findFontKey(QString::fromWCharArray(f->elfFullName)); - if (!key && (tm->ntmTm.tmPitchAndFamily & TMPF_TRUETYPE) && localizedName(faceName)) + if (!key && ttf && localizedName(faceName)) key = findFontKey(getEnglishName(faceName)); } if (key) { @@ -595,7 +599,6 @@ static int QT_WIN_CALLBACK populateFontFamilies(ENUMLOGFONTEX* f, NEWTEXTMETRICE context->seenSystemDefaultFont = true; // Register current font's english name as alias - const bool ttf = (tm->ntmTm.tmPitchAndFamily & TMPF_TRUETYPE); if (ttf && localizedName(faceName)) { const QString englishName = getEnglishName(faceName); if (!englishName.isEmpty()) { @@ -619,7 +622,7 @@ void QWindowsFontDatabaseFT::populateFontDatabase() lf.lfFaceName[0] = 0; lf.lfPitchAndFamily = 0; PopulateFamiliesContext context(QWindowsFontDatabase::systemDefaultFont().family()); - EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)populateFontFamilies, reinterpret_cast(&context), 0); + EnumFontFamiliesEx(dummy, &lf, populateFontFamilies, reinterpret_cast(&context), 0); ReleaseDC(0, dummy); // Work around EnumFontFamiliesEx() not listing the system font if (!context.seenSystemDefaultFont) From 6c7c34f219b6d156428d3fae79a09a2c68814ce6 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 16 Feb 2016 08:47:51 +0100 Subject: [PATCH 47/62] winrt: Disable tests which connect to localhost WinRT does not allow do connect to the localhost due to security constraints and sandboxing. Hence we need to disable those currently. Change-Id: Idb8c71397a41e5fa5bad9d618dba1bb389e71b9c Reviewed-by: Oliver Wolff --- tests/auto/corelib/kernel/qobject/tst_qobject.cpp | 3 +++ .../kernel/qsocketnotifier/tst_qsocketnotifier.cpp | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index f7c1f03c0fa..0d43b09d6b7 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -1848,6 +1848,8 @@ void tst_QObject::moveToThread() thread.wait(); } + // WinRT does not allow connection to localhost +#ifndef Q_OS_WINRT { // make sure socket notifiers are moved with the object MoveToThreadThread thread; @@ -1883,6 +1885,7 @@ void tst_QObject::moveToThread() QMetaObject::invokeMethod(socket, "deleteLater", Qt::QueuedConnection); thread.wait(); } +#endif } diff --git a/tests/auto/corelib/kernel/qsocketnotifier/tst_qsocketnotifier.cpp b/tests/auto/corelib/kernel/qsocketnotifier/tst_qsocketnotifier.cpp index f49da1f5a8a..95e924bd77a 100644 --- a/tests/auto/corelib/kernel/qsocketnotifier/tst_qsocketnotifier.cpp +++ b/tests/auto/corelib/kernel/qsocketnotifier/tst_qsocketnotifier.cpp @@ -131,6 +131,10 @@ signals: void tst_QSocketNotifier::unexpectedDisconnection() { +#ifdef Q_OS_WINRT + // WinRT does not allow a connection to the localhost + QSKIP("Local connection not allowed", SkipAll); +#else /* Given two sockets and two QSocketNotifiers registered on each their socket. If both sockets receive data, and the first slot @@ -196,6 +200,7 @@ void tst_QSocketNotifier::unexpectedDisconnection() writeEnd1->close(); writeEnd2->close(); server.close(); +#endif // !Q_OS_WINRT } class MixingWithTimersHelper : public QObject @@ -234,6 +239,9 @@ void MixingWithTimersHelper::socketFired() void tst_QSocketNotifier::mixingWithTimers() { +#ifdef Q_OS_WINRT + QSKIP("WinRT does not allow connection to localhost", SkipAll); +#else QTimer timer; timer.setInterval(0); timer.start(); @@ -258,6 +266,7 @@ void tst_QSocketNotifier::mixingWithTimers() QCOMPARE(helper.timerActivated, true); QTRY_COMPARE(helper.socketActivated, true); +#endif // !Q_OS_WINRT } #ifdef Q_OS_UNIX From 8b0dc802943358d0245a343533f0ffb1a55c6f76 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 16 Feb 2016 08:50:55 +0100 Subject: [PATCH 48/62] winrt: Fix usage of testdata testdata needs to be deployed to temp and current directory needs to be set to that directory for the test to succeed. Change-Id: I2dd023af9073d90afbb4ad60fcfb50bb1af4e159 Reviewed-by: Oliver Wolff --- .../auto/corelib/kernel/qtranslator/tst_qtranslator.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp index 2707b6df41d..c2290add5bc 100644 --- a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp +++ b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp @@ -58,6 +58,7 @@ private slots: private: int languageChangeEventCounter; + QSharedPointer dataDir; }; tst_QTranslator::tst_QTranslator() @@ -90,8 +91,16 @@ void tst_QTranslator::initTestCase() // chdir into the directory containing our testdata, // to make the code simpler (load testdata via relative paths) +#ifdef Q_OS_WINRT + // ### TODO: Use this for all platforms in 5.7 + dataDir = QEXTRACTTESTDATA(QStringLiteral("/")); + QVERIFY2(!dataDir.isNull(), qPrintable("Could not extract test data")); + QVERIFY2(QDir::setCurrent(dataDir->path()), qPrintable("Could not chdir to " + dataDir->path())); +#else // !Q_OS_WINRT QString testdata_dir = QFileInfo(QFINDTESTDATA("hellotr_la.qm")).absolutePath(); QVERIFY2(QDir::setCurrent(testdata_dir), qPrintable("Could not chdir to " + testdata_dir)); +#endif // !Q_OS_WINRT + } bool tst_QTranslator::eventFilter(QObject *, QEvent *event) From ad16703fa818b6d2a867b862bbbe51d9517d9fb9 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 16 Feb 2016 08:48:58 +0100 Subject: [PATCH 49/62] Update testdata Some entries were not updated and tests failed to succeed on platforms which need to deploy content/testdata. Change-Id: Ieb2b44c375b04cbaaecc1fb2303cc2478b86a100 Reviewed-by: Oliver Wolff --- tests/auto/corelib/json/json.pro | 2 +- tests/auto/corelib/kernel/qtranslator/qtranslator.pro | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/corelib/json/json.pro b/tests/auto/corelib/json/json.pro index 237e20685aa..899060764fd 100644 --- a/tests/auto/corelib/json/json.pro +++ b/tests/auto/corelib/json/json.pro @@ -4,7 +4,7 @@ CONFIG -= app_bundle CONFIG += testcase CONFIG += parallel_test -!android:TESTDATA += test.json test.bjson test3.json test2.json +!android:TESTDATA += bom.json test.json test.bjson test3.json test2.json else:RESOURCES += json.qrc SOURCES += tst_qtjson.cpp diff --git a/tests/auto/corelib/kernel/qtranslator/qtranslator.pro b/tests/auto/corelib/kernel/qtranslator/qtranslator.pro index e588f443704..c9b160a8d1d 100644 --- a/tests/auto/corelib/kernel/qtranslator/qtranslator.pro +++ b/tests/auto/corelib/kernel/qtranslator/qtranslator.pro @@ -5,5 +5,5 @@ SOURCES = tst_qtranslator.cpp RESOURCES += qtranslator.qrc android:!android-no-sdk: RESOURCES += android_testdata.qrc -else: TESTDATA += hellotr_la.qm msgfmt_from_po.qm +else: TESTDATA += dependencies_la.qm hellotr_la.qm msgfmt_from_po.qm From e7a06c984364a3ffb86b32921aa60672f7b71600 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Mon, 15 Feb 2016 16:01:21 +0100 Subject: [PATCH 50/62] winrt: Fix clipboard Native implementation was missing and so far it only used the Qt internal fallback mode. Unfortunately this does not apply to Windows Phone 8.1. Task-number: QTBUG-49766 Change-Id: I8cbbb0c843d077d7df1396d673fedeab2799b5a6 Reviewed-by: Oliver Wolff --- .../platforms/winrt/qwinrtclipboard.cpp | 185 ++++++++++++++++++ src/plugins/platforms/winrt/qwinrtclipboard.h | 78 ++++++++ .../platforms/winrt/qwinrtintegration.cpp | 9 + .../platforms/winrt/qwinrtintegration.h | 1 + src/plugins/platforms/winrt/winrt.pro | 2 + 5 files changed, 275 insertions(+) create mode 100644 src/plugins/platforms/winrt/qwinrtclipboard.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtclipboard.h diff --git a/src/plugins/platforms/winrt/qwinrtclipboard.cpp b/src/plugins/platforms/winrt/qwinrtclipboard.cpp new file mode 100644 index 00000000000..4e71490902f --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtclipboard.cpp @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwinrtclipboard.h" + +#include +#include +#include + +#include + +#include + +using namespace ABI::Windows::ApplicationModel::DataTransfer; +using namespace ABI::Windows::Foundation; +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; + +typedef IEventHandler ContentChangedHandler; + +#define RETURN_NULLPTR_IF_FAILED(msg) RETURN_IF_FAILED(msg, return nullptr) + +QT_BEGIN_NAMESPACE + +QWinRTClipboard::QWinRTClipboard() +{ +#ifndef Q_OS_WINPHONE + QEventDispatcherWinRT::runOnXamlThread([this]() { + HRESULT hr; + hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_DataTransfer_Clipboard).Get(), + &m_nativeClipBoard); + Q_ASSERT_SUCCEEDED(hr); + + EventRegistrationToken tok; + hr = m_nativeClipBoard->add_ContentChanged(Callback(this, &QWinRTClipboard::onContentChanged).Get(), &tok); + Q_ASSERT_SUCCEEDED(hr); + + return hr; + }); +#endif // !Q_OS_WINPHONE +} + +QMimeData *QWinRTClipboard::mimeData(QClipboard::Mode mode) +{ + if (!supportsMode(mode)) + return nullptr; + +#ifndef Q_OS_WINPHONE + ComPtr view; + HRESULT hr; + hr = m_nativeClipBoard->GetContent(&view); + RETURN_NULLPTR_IF_FAILED("Could not get clipboard content."); + + ComPtr> op; + HString result; + // This throws a security exception (WinRT originate error / 0x40080201. + // Unfortunately there seems to be no way to avoid this, neither + // running on the XAML thread, nor some other way. Stack Overflow + // confirms this problem since Windows (Phone) 8.0. + hr = view->GetTextAsync(&op); + RETURN_NULLPTR_IF_FAILED("Could not get clipboard text."); + + hr = QWinRTFunctions::await(op, result.GetAddressOf()); + RETURN_NULLPTR_IF_FAILED("Could not get clipboard text content"); + + quint32 size; + const wchar_t *textStr = result.GetRawBuffer(&size); + QString text = QString::fromWCharArray(textStr, size); + text.replace(QStringLiteral("\r\n"), QStringLiteral("\n")); + m_mimeData.setText(text); + + return &m_mimeData; +#else // Q_OS_WINPHONE + return QPlatformClipboard::mimeData(mode); +#endif // Q_OS_WINPHONE +} + +// Inspired by QWindowsMimeText::convertFromMime +inline QString convertToWindowsLineEnding(const QString &text) +{ + const QChar *u = text.unicode(); + QString res; + const int s = text.length(); + int maxsize = s + s / 40 + 3; + res.resize(maxsize); + int ri = 0; + bool cr = false; + for (int i = 0; i < s; ++i) { + if (*u == QLatin1Char('\r')) + cr = true; + else { + if (*u == QLatin1Char('\n') && !cr) + res[ri++] = QLatin1Char('\r'); + cr = false; + } + res[ri++] = *u; + if (ri+3 >= maxsize) { + maxsize += maxsize / 4; + res.resize(maxsize); + } + ++u; + } + res.truncate(ri); + return res; +} + +void QWinRTClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) +{ + if (!supportsMode(mode)) + return; + +#ifndef Q_OS_WINPHONE + const QString text = data->text(); + HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, text]() { + HRESULT hr; + ComPtr package; + hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_DataTransfer_DataPackage).Get(), + &package); + + const QString nativeString = convertToWindowsLineEnding(text); + HStringReference textRef(reinterpret_cast(nativeString.utf16()), nativeString.length()); + + hr = package->SetText(textRef.Get()); + RETURN_HR_IF_FAILED("Could not set text to clipboard data package."); + + hr = m_nativeClipBoard->SetContent(package.Get()); + RETURN_HR_IF_FAILED("Could not set clipboard content."); + return S_OK; + }); + RETURN_VOID_IF_FAILED("Could not set clipboard text."); + emitChanged(mode); +#else // Q_OS_WINPHONE + QPlatformClipboard::setMimeData(data, mode); +#endif // Q_OS_WINPHONE +} + +bool QWinRTClipboard::supportsMode(QClipboard::Mode mode) const +{ +#ifndef Q_OS_WINPHONE + return mode == QClipboard::Clipboard; +#else + return QPlatformClipboard::supportsMode(mode); +#endif +} + +HRESULT QWinRTClipboard::onContentChanged(IInspectable *, IInspectable *) +{ + emitChanged(QClipboard::Clipboard); + return S_OK; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtclipboard.h b/src/plugins/platforms/winrt/qwinrtclipboard.h new file mode 100644 index 00000000000..1fb10bdfc02 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtclipboard.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTPLATFORMCLIPBOARD_H +#define QWINRTPLATFORMCLIPBOARD_H + +#include +#include + +#include + +#ifndef Q_OS_WINPHONE +namespace ABI { + namespace Windows { + namespace ApplicationModel { + namespace DataTransfer { + struct IClipboardStatics; + } + } + } +} +#endif // !Q_OS_WINPHONE + +QT_BEGIN_NAMESPACE + +class QWinRTClipboard: public QPlatformClipboard +{ +public: + QWinRTClipboard(); + + QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE; + void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE; + bool supportsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE; + + HRESULT onContentChanged(IInspectable *, IInspectable *); +private: +#ifndef Q_OS_WINPHONE + Microsoft::WRL::ComPtr m_nativeClipBoard; +#endif + QMimeData m_mimeData; +}; + +QT_END_NAMESPACE + +#endif // QWINRTPLATFORMCLIPBOARD_H diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index 9dac667ce54..30c0e81e216 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -44,6 +44,7 @@ #include "qwinrteglcontext.h" #include "qwinrtfontdatabase.h" #include "qwinrttheme.h" +#include "qwinrtclipboard.h" #include #include @@ -111,6 +112,7 @@ class QWinRTIntegrationPrivate public: QPlatformFontDatabase *fontDatabase; QPlatformServices *platformServices; + QPlatformClipboard *clipboard; QWinRTScreen *mainScreen; QScopedPointer inputContext; @@ -195,6 +197,7 @@ QWinRTIntegration::QWinRTIntegration() : d_ptr(new QWinRTIntegrationPrivate) screenAdded(d->mainScreen); d->platformServices = new QWinRTServices; + d->clipboard = new QWinRTClipboard; } QWinRTIntegration::~QWinRTIntegration() @@ -300,6 +303,12 @@ QPlatformServices *QWinRTIntegration::services() const return d->platformServices; } +QPlatformClipboard *QWinRTIntegration::clipboard() const +{ + Q_D(const QWinRTIntegration); + return d->clipboard; +} + Qt::KeyboardModifiers QWinRTIntegration::queryKeyboardModifiers() const { Q_D(const QWinRTIntegration); diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h index 9bf5d27973e..1ed286ab2e0 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.h +++ b/src/plugins/platforms/winrt/qwinrtintegration.h @@ -93,6 +93,7 @@ public: QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE; QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE; QPlatformServices *services() const Q_DECL_OVERRIDE; + QPlatformClipboard *clipboard() const Q_DECL_OVERRIDE; Qt::KeyboardModifiers queryKeyboardModifiers() const Q_DECL_OVERRIDE; QStringList themeNames() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro index be6aad02d1d..991ec1789b0 100644 --- a/src/plugins/platforms/winrt/winrt.pro +++ b/src/plugins/platforms/winrt/winrt.pro @@ -16,6 +16,7 @@ INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/freetype/include SOURCES = \ main.cpp \ qwinrtbackingstore.cpp \ + qwinrtclipboard.cpp \ qwinrtcursor.cpp \ qwinrteglcontext.cpp \ qwinrteventdispatcher.cpp \ @@ -33,6 +34,7 @@ SOURCES = \ HEADERS = \ qwinrtbackingstore.h \ + qwinrtclipboard.h \ qwinrtcursor.h \ qwinrteglcontext.h \ qwinrteventdispatcher.h \ From 5b727576b15f40f9759c2b4317933ebd2a50fdf5 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Fri, 29 Jan 2016 15:19:01 +0100 Subject: [PATCH 51/62] winrt: add logging to platform plugin Task-number: QTBUG-38114 Change-Id: I24c96bb2e29e1bbfe93dfe45aa764451aa9ddde8 Reviewed-by: Oliver Wolff --- .../platforms/winrt/qwinrtbackingstore.cpp | 13 +++++++++ .../platforms/winrt/qwinrtbackingstore.h | 4 +++ .../platforms/winrt/qwinrtfontdatabase.cpp | 27 +++++++++++++++++++ .../platforms/winrt/qwinrtfontdatabase.h | 3 +++ .../platforms/winrt/qwinrtinputcontext.cpp | 11 ++++++++ .../platforms/winrt/qwinrtinputcontext.h | 3 +++ src/plugins/platforms/winrt/qwinrttheme.cpp | 7 +++++ src/plugins/platforms/winrt/qwinrttheme.h | 3 +++ src/plugins/platforms/winrt/qwinrtwindow.cpp | 21 +++++++++++++-- src/plugins/platforms/winrt/qwinrtwindow.h | 3 +++ 10 files changed, 93 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp index 4517200a2d2..fc7ab15f731 100644 --- a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp +++ b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp @@ -47,6 +47,9 @@ QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcQpaBackingStore, "qt.qpa.backingstore") +Q_LOGGING_CATEGORY(lcQpaBackingStoreVerbose, "qt.qpa.backingstore.verbose") + class QWinRTBackingStorePrivate { public: @@ -62,6 +65,7 @@ QWinRTBackingStore::QWinRTBackingStore(QWindow *window) : QPlatformBackingStore(window), d_ptr(new QWinRTBackingStorePrivate) { Q_D(QWinRTBackingStore); + qCDebug(lcQpaBackingStore) << __FUNCTION__ << this << window; d->initialized = false; d->screen = static_cast(window->screen()->handle()); @@ -73,6 +77,7 @@ QWinRTBackingStore::QWinRTBackingStore(QWindow *window) bool QWinRTBackingStore::initialize() { Q_D(QWinRTBackingStore); + qCDebug(lcQpaBackingStoreVerbose) << __FUNCTION__ << d->initialized; if (d->initialized) return true; @@ -94,6 +99,7 @@ bool QWinRTBackingStore::initialize() QWinRTBackingStore::~QWinRTBackingStore() { + qCDebug(lcQpaBackingStore) << __FUNCTION__ << this; } QPaintDevice *QWinRTBackingStore::paintDevice() @@ -107,6 +113,8 @@ void QWinRTBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo Q_D(QWinRTBackingStore); Q_UNUSED(offset) + qCDebug(lcQpaBackingStoreVerbose) << __FUNCTION__ << this << window << region; + if (d->size.isEmpty()) return; @@ -140,6 +148,8 @@ void QWinRTBackingStore::resize(const QSize &size, const QRegion &staticContents Q_D(QWinRTBackingStore); Q_UNUSED(staticContents) + qCDebug(lcQpaBackingStoreVerbose) << __FUNCTION__ << this << size; + if (!initialize()) return; @@ -169,11 +179,14 @@ QImage QWinRTBackingStore::toImage() const void QWinRTBackingStore::beginPaint(const QRegion ®ion) { + qCDebug(lcQpaBackingStoreVerbose) << __FUNCTION__ << this << region; + resize(window()->size(), region); } void QWinRTBackingStore::endPaint() { + qCDebug(lcQpaBackingStoreVerbose) << __FUNCTION__ << this; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.h b/src/plugins/platforms/winrt/qwinrtbackingstore.h index 20b27a38650..b5d9dfed4fa 100644 --- a/src/plugins/platforms/winrt/qwinrtbackingstore.h +++ b/src/plugins/platforms/winrt/qwinrtbackingstore.h @@ -39,9 +39,13 @@ #include #include +#include QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcQpaBackingStore) +Q_DECLARE_LOGGING_CATEGORY(lcQpaBackingStoreVerbose) + class QWinRTScreen; class QWinRTBackingStorePrivate; diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp index 793256a83f4..22fb8cb63e2 100644 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp @@ -47,6 +47,20 @@ using namespace Microsoft::WRL; QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcQpaFonts, "qt.qpa.fonts") + +QDebug operator<<(QDebug d, const QFontDef &def) +{ + QDebugStateSaver saver(d); + d.nospace(); + d << "Family=" << def.family << " Stylename=" << def.styleName + << " pointsize=" << def.pointSize << " pixelsize=" << def.pixelSize + << " styleHint=" << def.styleHint << " weight=" << def.weight + << " stretch=" << def.stretch << " hintingPreference=" + << def.hintingPreference; + return d; +} + // Based on unicode range tables at http://www.microsoft.com/typography/otspec/os2.htm#ur static QFontDatabase::WritingSystem writingSystemFromUnicodeRange(const DWRITE_UNICODE_RANGE &range) { @@ -114,6 +128,7 @@ static QFontDatabase::WritingSystem writingSystemFromUnicodeRange(const DWRITE_U QString QWinRTFontDatabase::fontDir() const { + qCDebug(lcQpaFonts) << __FUNCTION__; QString fontDirectory = QBasicFontDatabase::fontDir(); if (!QFile::exists(fontDirectory)) { // Fall back to app directory + fonts, and just app directory after that @@ -130,6 +145,8 @@ QString QWinRTFontDatabase::fontDir() const QWinRTFontDatabase::~QWinRTFontDatabase() { + qCDebug(lcQpaFonts) << __FUNCTION__; + foreach (IDWriteFontFile *fontFile, m_fonts.keys()) fontFile->Release(); @@ -149,6 +166,8 @@ bool QWinRTFontDatabase::fontsAlwaysScalable() const void QWinRTFontDatabase::populateFontDatabase() { + qCDebug(lcQpaFonts) << __FUNCTION__; + ComPtr factory; HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, __uuidof(IDWriteFactory1), &factory); if (FAILED(hr)) { @@ -204,6 +223,8 @@ void QWinRTFontDatabase::populateFontDatabase() void QWinRTFontDatabase::populateFamily(const QString &familyName) { + qCDebug(lcQpaFonts) << __FUNCTION__ << familyName; + IDWriteFontFamily *fontFamily = m_fontFamilies.value(familyName); if (!fontFamily) { qWarning("The font family %s was not found.", qPrintable(familyName)); @@ -367,6 +388,8 @@ void QWinRTFontDatabase::populateFamily(const QString &familyName) QFontEngine *QWinRTFontDatabase::fontEngine(const QFontDef &fontDef, void *handle) { + qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDEF" << fontDef << handle; + if (!handle) // Happens if a font family population failed return 0; @@ -436,6 +459,8 @@ QStringList QWinRTFontDatabase::fallbacksForFamily(const QString &family, QFont: Q_UNUSED(styleHint) Q_UNUSED(script) + qCDebug(lcQpaFonts) << __FUNCTION__ << family; + QStringList result; if (family == QLatin1String("Helvetica")) result.append(QStringLiteral("Arial")); @@ -445,6 +470,8 @@ QStringList QWinRTFontDatabase::fallbacksForFamily(const QString &family, QFont: void QWinRTFontDatabase::releaseHandle(void *handle) { + qCDebug(lcQpaFonts) << __FUNCTION__ << handle; + if (!handle) return; diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.h b/src/plugins/platforms/winrt/qwinrtfontdatabase.h index 41619f5bd84..e8495e202f2 100644 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.h +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.h @@ -38,12 +38,15 @@ #define QWINRTFONTDATABASE_H #include +#include struct IDWriteFontFile; struct IDWriteFontFamily; QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcQpaFonts) + struct FontDescription { quint32 index; diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp index 9228ef8d622..72fc3787604 100644 --- a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp +++ b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp @@ -54,6 +54,8 @@ typedef ITypedEventHandler InputPaneV QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcQpaInputMethods, "qt.qpa.input.methods") + inline QRectF getInputPaneRect(IInputPane *pane, qreal scaleFactor) { Rect rect; @@ -78,6 +80,8 @@ inline QRectF getInputPaneRect(IInputPane *pane, qreal scaleFactor) QWinRTInputContext::QWinRTInputContext(QWinRTScreen *screen) : m_screen(screen) { + qCDebug(lcQpaInputMethods) << __FUNCTION__ << screen; + IInputPaneStatics *statics; if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_InputPane).Get(), &statics))) { @@ -114,6 +118,7 @@ bool QWinRTInputContext::isInputPanelVisible() const HRESULT QWinRTInputContext::onShowing(IInputPane *pane, IInputPaneVisibilityEventArgs *) { + qCDebug(lcQpaInputMethods) << __FUNCTION__ << pane; m_isInputPanelVisible = true; emitInputPanelVisibleChanged(); return handleVisibilityChange(pane); @@ -121,6 +126,7 @@ HRESULT QWinRTInputContext::onShowing(IInputPane *pane, IInputPaneVisibilityEven HRESULT QWinRTInputContext::onHiding(IInputPane *pane, IInputPaneVisibilityEventArgs *) { + qCDebug(lcQpaInputMethods) << __FUNCTION__ << pane; m_isInputPanelVisible = false; emitInputPanelVisibleChanged(); return handleVisibilityChange(pane); @@ -128,6 +134,7 @@ HRESULT QWinRTInputContext::onHiding(IInputPane *pane, IInputPaneVisibilityEvent HRESULT QWinRTInputContext::handleVisibilityChange(IInputPane *pane) { + qCDebug(lcQpaInputMethods) << __FUNCTION__ << pane; const QRectF keyboardRect = getInputPaneRect(pane, m_screen->scaleFactor()); if (m_keyboardRect != keyboardRect) { m_keyboardRect = keyboardRect; @@ -165,6 +172,8 @@ static HRESULT getInputPane(ComPtr *inputPane2) void QWinRTInputContext::showInputPanel() { + qCDebug(lcQpaInputMethods) << __FUNCTION__; + QEventDispatcherWinRT::runOnXamlThread([&]() { ComPtr inputPane; HRESULT hr = getInputPane(&inputPane); @@ -180,6 +189,8 @@ void QWinRTInputContext::showInputPanel() void QWinRTInputContext::hideInputPanel() { + qCDebug(lcQpaInputMethods) << __FUNCTION__; + QEventDispatcherWinRT::runOnXamlThread([&]() { ComPtr inputPane; HRESULT hr = getInputPane(&inputPane); diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.h b/src/plugins/platforms/winrt/qwinrtinputcontext.h index 6f88ff46e66..d5a1a40efcc 100644 --- a/src/plugins/platforms/winrt/qwinrtinputcontext.h +++ b/src/plugins/platforms/winrt/qwinrtinputcontext.h @@ -39,6 +39,7 @@ #include #include +#include #include @@ -58,6 +59,8 @@ namespace ABI { QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcQpaInputMethods) + class QWinRTScreen; class QWinRTInputContext : public QPlatformInputContext { diff --git a/src/plugins/platforms/winrt/qwinrttheme.cpp b/src/plugins/platforms/winrt/qwinrttheme.cpp index 7d09551f5bc..7ef13fd0aa6 100644 --- a/src/plugins/platforms/winrt/qwinrttheme.cpp +++ b/src/plugins/platforms/winrt/qwinrttheme.cpp @@ -56,6 +56,8 @@ using namespace ABI::Windows::UI::ViewManagement; QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcQpaTheme, "qt.qpa.theme") + static IUISettings *uiSettings() { static ComPtr settings; @@ -285,12 +287,14 @@ QWinRTTheme::QWinRTTheme() : d_ptr(new QWinRTThemePrivate) { Q_D(QWinRTTheme); + qCDebug(lcQpaTheme) << __FUNCTION__; nativeColorSettings(d->palette); } bool QWinRTTheme::usePlatformNativeDialog(DialogType type) const { + qCDebug(lcQpaTheme) << __FUNCTION__ << type; static bool useNativeDialogs = qEnvironmentVariableIsSet("QT_USE_WINRT_NATIVE_DIALOGS") ? qEnvironmentVariableIntValue("QT_USE_WINRT_NATIVE_DIALOGS") : true; @@ -301,6 +305,7 @@ bool QWinRTTheme::usePlatformNativeDialog(DialogType type) const QPlatformDialogHelper *QWinRTTheme::createPlatformDialogHelper(DialogType type) const { + qCDebug(lcQpaTheme) << __FUNCTION__ << type; switch (type) { case FileDialog: return new QWinRTFileDialogHelper; @@ -314,6 +319,7 @@ QPlatformDialogHelper *QWinRTTheme::createPlatformDialogHelper(DialogType type) QVariant QWinRTTheme::styleHint(QPlatformIntegration::StyleHint hint) { + qCDebug(lcQpaTheme) << __FUNCTION__ << hint; HRESULT hr; switch (hint) { case QPlatformIntegration::CursorFlashTime: { @@ -363,6 +369,7 @@ QVariant QWinRTTheme::styleHint(QPlatformIntegration::StyleHint hint) const QPalette *QWinRTTheme::palette(Palette type) const { Q_D(const QWinRTTheme); + qCDebug(lcQpaTheme) << __FUNCTION__ << type; if (type == SystemPalette) return &d->palette; return QPlatformTheme::palette(type); diff --git a/src/plugins/platforms/winrt/qwinrttheme.h b/src/plugins/platforms/winrt/qwinrttheme.h index 2e159cbd555..e1a0e149648 100644 --- a/src/plugins/platforms/winrt/qwinrttheme.h +++ b/src/plugins/platforms/winrt/qwinrttheme.h @@ -39,9 +39,12 @@ #include #include +#include QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcQpaTheme) + class QWinRTThemePrivate; class QWinRTTheme : public QPlatformTheme { diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp index 034879c4784..07904ffbf79 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.cpp +++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp @@ -69,6 +69,8 @@ using namespace ABI::Windows::UI::Xaml::Controls; QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcQpaWindows, "qt.qpa.windows"); + static void setUIElementVisibility(IUIElement *uiElement, bool visibility) { Q_ASSERT(uiElement); @@ -101,6 +103,7 @@ QWinRTWindow::QWinRTWindow(QWindow *window) , d_ptr(new QWinRTWindowPrivate) { Q_D(QWinRTWindow); + qCDebug(lcQpaWindows) << __FUNCTION__ << this; d->surface = EGL_NO_SURFACE; d->display = EGL_NO_DISPLAY; @@ -161,6 +164,7 @@ QWinRTWindow::QWinRTWindow(QWindow *window) QWinRTWindow::~QWinRTWindow() { Q_D(QWinRTWindow); + qCDebug(lcQpaWindows) << __FUNCTION__ << this; HRESULT hr; hr = QEventDispatcherWinRT::runOnXamlThread([d]() { @@ -187,6 +191,8 @@ QWinRTWindow::~QWinRTWindow() if (!d->surface) return; + qCDebug(lcQpaWindows) << __FUNCTION__ << ": Destroying surface"; + EGLBoolean value = eglDestroySurface(d->display, d->surface); d->surface = EGL_NO_SURFACE; if (value == EGL_FALSE) @@ -214,12 +220,15 @@ bool QWinRTWindow::isExposed() const void QWinRTWindow::setGeometry(const QRect &rect) { Q_D(QWinRTWindow); + qCDebug(lcQpaWindows) << __FUNCTION__ << this << rect; const Qt::WindowFlags windowFlags = window()->flags(); const Qt::WindowFlags windowType = windowFlags & Qt::WindowType_Mask; if (window()->isTopLevel() && (windowType == Qt::Window || windowType == Qt::Dialog)) { - QPlatformWindow::setGeometry(windowFlags & Qt::MaximizeUsingFullscreenGeometryHint - ? d->screen->geometry() : d->screen->availableGeometry()); + const QRect screenRect = windowFlags & Qt::MaximizeUsingFullscreenGeometryHint + ? d->screen->geometry() : d->screen->availableGeometry(); + qCDebug(lcQpaWindows) << __FUNCTION__ << "top-level, overwrite" << screenRect; + QPlatformWindow::setGeometry(screenRect); QWindowSystemInterface::handleGeometryChange(window(), geometry()); } else { QPlatformWindow::setGeometry(rect); @@ -243,6 +252,8 @@ void QWinRTWindow::setGeometry(const QRect &rect) Q_ASSERT_SUCCEEDED(hr); hr = frameworkElement->put_Height(size.height()); Q_ASSERT_SUCCEEDED(hr); + qCDebug(lcQpaWindows) << __FUNCTION__ << "(setGeometry Xaml)" << this + << topLeft << size; return S_OK; }); Q_ASSERT_SUCCEEDED(hr); @@ -251,6 +262,8 @@ void QWinRTWindow::setGeometry(const QRect &rect) void QWinRTWindow::setVisible(bool visible) { Q_D(QWinRTWindow); + qCDebug(lcQpaWindows) << __FUNCTION__ << this << visible; + if (!window()->isTopLevel()) return; if (visible) { @@ -272,6 +285,7 @@ void QWinRTWindow::setWindowTitle(const QString &title) void QWinRTWindow::raise() { Q_D(QWinRTWindow); + qCDebug(lcQpaWindows) << __FUNCTION__ << this; if (!window()->isTopLevel()) return; d->screen->raise(window()); @@ -280,6 +294,7 @@ void QWinRTWindow::raise() void QWinRTWindow::lower() { Q_D(QWinRTWindow); + qCDebug(lcQpaWindows) << __FUNCTION__ << this; if (!window()->isTopLevel()) return; d->screen->lower(window()); @@ -299,6 +314,8 @@ qreal QWinRTWindow::devicePixelRatio() const void QWinRTWindow::setWindowState(Qt::WindowState state) { Q_D(QWinRTWindow); + qCDebug(lcQpaWindows) << __FUNCTION__ << this << state; + if (d->state == state) return; diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h index 9ac7adbf4d3..36f5b9de847 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.h +++ b/src/plugins/platforms/winrt/qwinrtwindow.h @@ -37,12 +37,15 @@ #ifndef QWINRTWINDOW_H #define QWINRTWINDOW_H +#include #include #include #include QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcQpaWindows) + class QWinRTWindowPrivate; class QWinRTWindow : public QPlatformWindow { From a3b8e355fc17783a5d4badfb9ad50247655000cd Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Fri, 12 Feb 2016 15:31:07 +0300 Subject: [PATCH 52/62] QListView: fix skipping indexes in selectedIndexes(). Remove spurious increment of i. Task-number: QTBUG-51086 Change-Id: I4307a6728de1e7f25c8afa31fe2066f92373f3fc Reviewed-by: Edward Welbourne Reviewed-by: Oswald Buddenhagen Reviewed-by: Marc Mutz --- src/widgets/itemviews/qlistview.cpp | 2 +- .../itemviews/qlistview/tst_qlistview.cpp | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index 9c79509874f..a17d89e7358 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -1437,7 +1437,7 @@ QModelIndexList QListView::selectedIndexes() const return QModelIndexList(); QModelIndexList viewSelected = d->selectionModel->selectedIndexes(); - for (int i = 0; i < viewSelected.count(); ++i) { + for (int i = 0; i < viewSelected.count();) { const QModelIndex &index = viewSelected.at(i); if (!isIndexHidden(index) && index.parent() == d->root && index.column() == d->column) ++i; diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp index 5b206af357d..3cf9f7fe0b1 100644 --- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp +++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp @@ -152,6 +152,7 @@ private slots: void taskQTBUG_39902_mutualScrollBars_data(); void taskQTBUG_39902_mutualScrollBars(); void horizontalScrollingByVerticalWheelEvents(); + void taskQTBUG_51086_skippingIndexesInSelectedIndexes(); }; // Testing get/set functions @@ -2493,5 +2494,32 @@ void tst_QListView::horizontalScrollingByVerticalWheelEvents() QVERIFY(lv.verticalScrollBar()->value() > vValue); } +void tst_QListView::taskQTBUG_51086_skippingIndexesInSelectedIndexes() +{ + // simple way to get access to selectedIndexes() + class QListViewWithPublicSelectedIndexes : public QListView + { + public: + using QListView::selectedIndexes; + }; + + QStandardItemModel data(10, 1); + QItemSelectionModel selections(&data); + QListViewWithPublicSelectedIndexes list; + list.setModel(&data); + list.setSelectionModel(&selections); + + list.setRowHidden(7, true); + list.setRowHidden(8, true); + + for (int i = 0, count = data.rowCount(); i < count; ++i) + selections.select(data.index(i, 0), QItemSelectionModel::Select); + + const QModelIndexList indexes = list.selectedIndexes(); + + QVERIFY(!indexes.contains(data.index(7, 0))); + QVERIFY(!indexes.contains(data.index(8, 0))); +} + QTEST_MAIN(tst_QListView) #include "tst_qlistview.moc" From 9212727813e808de8c136e26b113f8ed0e704e94 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 5 Feb 2016 10:45:20 -0800 Subject: [PATCH 53/62] QOpenGLExtensionMatcher: Fix possible use of unintialized memory Some drivers don't support GL_NUM_EXTENSIONS, so we may be reading random bits from numExtensions. Change-Id: Ibe61fa6d7c379f3f1428458edd3e0ddba0eb04d7 Task-number: QTBUG-48943 Reviewed-by: Laszlo Agocs --- src/gui/opengl/qopengl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/opengl/qopengl.cpp b/src/gui/opengl/qopengl.cpp index a77d6743ade..3dedd7d7be6 100644 --- a/src/gui/opengl/qopengl.cpp +++ b/src/gui/opengl/qopengl.cpp @@ -79,7 +79,7 @@ QOpenGLExtensionMatcher::QOpenGLExtensionMatcher() if (!glGetStringi) return; - GLint numExtensions; + GLint numExtensions = 0; funcs->glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions); for (int i = 0; i < numExtensions; ++i) { From 049fad42a26c32241206371e4d2baa16b12ee287 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Mon, 8 Feb 2016 15:26:17 -0800 Subject: [PATCH 54/62] QWindow: Make screen warning more informative Change-Id: Icd7933422e272434370ae6080348de6159d2e725 Reviewed-by: Friedemann Kleint --- src/gui/kernel/qwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 30cbed4aa8b..e0d991aaf8a 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -369,7 +369,7 @@ void QWindowPrivate::setTopLevelScreen(QScreen *newScreen, bool recreate) { Q_Q(QWindow); if (parentWindow) { - qWarning() << this << '(' << newScreen << "): Attempt to set a screen on a child window."; + qWarning() << q << '(' << newScreen << "): Attempt to set a screen on a child window."; return; } if (newScreen != topLevelScreen) { From 42b39f9827b8410077b0330cab41f20feeabf678 Mon Sep 17 00:00:00 2001 From: Ariel Molina Date: Sat, 13 Feb 2016 17:55:09 -0600 Subject: [PATCH 55/62] Add source device information to qDebug output of QTouchEvent This is a simplistic patch to make it easier to debug touch input when using multiple physical or virtual devices. Change-Id: I996237cdce5e0ff0c4a0660dabb0d190679ab585 Reviewed-by: Shawn Rutledge Reviewed-by: Robin Burchell --- src/gui/kernel/qevent.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 2ca17692db1..b0f7adf43a8 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3569,6 +3569,7 @@ static inline void formatTouchEvent(QDebug d, const QTouchEvent &t) { d << "QTouchEvent("; QtDebugUtils::formatQEnum(d, t.type()); + d << " device: " << t.device()->name(); d << " states: "; QtDebugUtils::formatQFlags(d, t.touchPointStates()); d << ", " << t.touchPoints().size() << " points: " << t.touchPoints() << ')'; From ed4ef55ec5710f64799adb2b26201356eba788c9 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 3 Feb 2016 15:55:25 +0100 Subject: [PATCH 56/62] QtNetwork: Silence Clang on Windows. Remove dead code and fix override. Task-number: QTBUG-50804 Change-Id: I9cc28507e549d56a1f15fcc54bb6f7465beef644 Reviewed-by: Edward Welbourne Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/network/socket/qnativesocketengine_win.cpp | 13 ------------- src/network/ssl/qsslsocket_openssl_p.h | 2 +- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index ca0a8b95d59..7b6be9ebf99 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -294,19 +294,6 @@ static inline QAbstractSocket::SocketType qt_socket_getType(qintptr socketDescri return QAbstractSocket::UnknownSocketType; } -/*! \internal - -*/ -static inline int qt_socket_getMaxMsgSize(qintptr socketDescriptor) -{ - int value = 0; - QT_SOCKLEN_T valueSize = sizeof(value); - if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *) &value, &valueSize) != 0) { - WS_ERROR_DEBUG(WSAGetLastError()); - } - return value; -} - // MS Transport Provider IOCTL to control // reporting PORT_UNREACHABLE messages // on UDP sockets via recv/WSARecv/etc. diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h index f27c8eb1f35..4085ae6b3f4 100644 --- a/src/network/ssl/qsslsocket_openssl_p.h +++ b/src/network/ssl/qsslsocket_openssl_p.h @@ -131,7 +131,7 @@ public: unsigned int tlsPskClientCallback(const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len); #ifdef Q_OS_WIN void fetchCaRootForCert(const QSslCertificate &cert); - void _q_caRootLoaded(QSslCertificate,QSslCertificate); + void _q_caRootLoaded(QSslCertificate,QSslCertificate) Q_DECL_OVERRIDE; #endif Q_AUTOTEST_EXPORT static long setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions); From 34472e946a11bf6e06ba9ed7b72f938ea6eede02 Mon Sep 17 00:00:00 2001 From: Vyacheslav Grigoryev Date: Tue, 16 Feb 2016 09:19:03 +0300 Subject: [PATCH 57/62] QSqlDriver: use table prefix in WHERE clauses If the WHERE clause is used in a query involving multiple tables, such as generated by QSqlRelationalTableModel, the table prefix may be necessary to disambiguate column references. It is harmless if not needed. Task-number: QTBUG-43320 Change-Id: I39e1ab7359bf748afa8bcd8578220e3abb3ee24a Reviewed-by: Mark Brand --- src/sql/kernel/qsqldriver.cpp | 38 ++++----- .../tst_qsqlrelationaltablemodel.cpp | 80 +++++++++---------- 2 files changed, 55 insertions(+), 63 deletions(-) diff --git a/src/sql/kernel/qsqldriver.cpp b/src/sql/kernel/qsqldriver.cpp index ccfc6e04f09..9ee8d67f560 100644 --- a/src/sql/kernel/qsqldriver.cpp +++ b/src/sql/kernel/qsqldriver.cpp @@ -476,31 +476,23 @@ QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName, s.prepend(QLatin1String("SELECT ")).append(QLatin1String(" FROM ")).append(tableName); break; case WhereStatement: - if (preparedStatement) { - for (int i = 0; i < rec.count(); ++i) { - s.append(prepareIdentifier(rec.fieldName(i), FieldName,this)); - if (rec.isNull(i)) - s.append(QLatin1String(" IS NULL")); - else - s.append(QLatin1String(" = ?")); - s.append(QLatin1String(" AND ")); - } - } else { - for (i = 0; i < rec.count(); ++i) { - s.append(prepareIdentifier(rec.fieldName(i), QSqlDriver::FieldName, this)); - QString val = formatValue(rec.field(i)); - if (val == QLatin1String("NULL")) - s.append(QLatin1String(" IS NULL")); - else - s.append(QLatin1String(" = ")).append(val); - s.append(QLatin1String(" AND ")); - } - } - if (!s.isEmpty()) { - s.prepend(QLatin1String("WHERE ")); - s.chop(5); // remove tailing AND + { + const QString tableNamePrefix = tableName.isEmpty() + ? QString() + : prepareIdentifier(tableName, QSqlDriver::TableName, this) + QLatin1Char('.'); + for (int i = 0; i < rec.count(); ++i) { + s.append(QLatin1String(i? " AND " : "WHERE ")); + s.append(tableNamePrefix); + s.append(prepareIdentifier(rec.fieldName(i), QSqlDriver::FieldName, this)); + if (rec.isNull(i)) + s.append(QLatin1String(" IS NULL")); + else if (preparedStatement) + s.append(QLatin1String(" = ?")); + else + s.append(QLatin1String(" = ")).append(formatValue(rec.field(i))); } break; + } case UpdateStatement: s.append(QLatin1String("UPDATE ")).append(tableName).append( QLatin1String(" SET ")); diff --git a/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp b/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp index 3702631275b..7007664c398 100644 --- a/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp +++ b/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp @@ -109,7 +109,7 @@ void tst_QSqlRelationalTableModel::recreateTestTables(QSqlDatabase db) QVERIFY_SQL( q, exec("insert into " + reltest1 + " values(5, 'nat', NULL, NULL)")); QVERIFY_SQL( q, exec("insert into " + reltest1 + " values(6, 'ale', NULL, 2)")); - QVERIFY_SQL( q, exec("create table " + reltest2 + " (tid int not null primary key, title varchar(20))")); + QVERIFY_SQL( q, exec("create table " + reltest2 + " (id int not null primary key, title varchar(20))")); QVERIFY_SQL( q, exec("insert into " + reltest2 + " values(1, 'herr')")); QVERIFY_SQL( q, exec("insert into " + reltest2 + " values(2, 'mister')")); @@ -201,7 +201,7 @@ void tst_QSqlRelationalTableModel::data() QSqlRelationalTableModel model(0, db); model.setTable(reltest1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); QVERIFY_SQL(model, select()); QCOMPARE(model.columnCount(), 4); @@ -246,7 +246,7 @@ void tst_QSqlRelationalTableModel::setData() model.setTable(reltest1); model.setSort(0, Qt::AscendingOrder); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); QVERIFY_SQL(model, select()); QVERIFY(model.setData(model.index(0, 1), QString("harry2"))); @@ -276,7 +276,7 @@ void tst_QSqlRelationalTableModel::setData() QCOMPARE(model.data(model.index(3, 1)).toString(), QString("boris2")); QCOMPARE(model.data(model.index(3, 2)).toInt(), 1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); QVERIFY_SQL(model, select()); QCOMPARE(model.data(model.index(0, 2)).toString(), QString("mister")); QCOMPARE(model.data(model.index(3,2)).toString(), QString("herr")); @@ -289,7 +289,7 @@ void tst_QSqlRelationalTableModel::setData() model.setTable(reltest1); model.setEditStrategy(QSqlTableModel::OnFieldChange); model.setSort(0, Qt::AscendingOrder); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); QVERIFY_SQL(model, select()); QVERIFY(model.setData(model.index(1,1), QString("trond2"))); @@ -307,7 +307,7 @@ void tst_QSqlRelationalTableModel::setData() QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond2")); QCOMPARE(model.data(model.index(2, 2)).toInt(), 2); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); QVERIFY_SQL(model, select()); QCOMPARE(model.data(model.index(2, 2)).toString(), QString("mister")); } @@ -317,12 +317,12 @@ void tst_QSqlRelationalTableModel::setData() QSqlRelationalTableModel model(0, db); model.setTable(reltest1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); //sybase doesn't allow tables with the same alias used twice as col names //so don't set up an identical relation when using the tds driver if (dbType != QSqlDriver::Sybase) - model.setRelation(3, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(3, QSqlRelation(reltest2, "id", "title")); model.setEditStrategy(QSqlTableModel::OnManualSubmit); model.setSort(0, Qt::AscendingOrder); @@ -351,9 +351,9 @@ void tst_QSqlRelationalTableModel::setData() QCOMPARE(model.data(model.index(3, 2)).toInt(), 1); QCOMPARE(model.data(model.index(0, 3)).toInt(), 1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); if (dbType != QSqlDriver::Sybase) - model.setRelation(3, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(3, QSqlRelation(reltest2, "id", "title")); QVERIFY_SQL(model, select()); QCOMPARE(model.data(model.index(3, 2)).toString(), QString("herr")); @@ -411,7 +411,7 @@ void tst_QSqlRelationalTableModel::multipleRelation() QSqlRelationalTableModel model(0, db); model.setTable(reltest1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); model.setRelation(3, QSqlRelation(reltest4, "id", "name")); model.setSort(0, Qt::AscendingOrder); QVERIFY_SQL(model, select()); @@ -425,7 +425,7 @@ void tst_QSqlRelationalTableModel::multipleRelation() // Redo same test in the LeftJoin mode model.setTable(reltest1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); model.setRelation(3, QSqlRelation(reltest4, "id", "name")); model.setSort(0, Qt::AscendingOrder); model.setJoinMode(QSqlRelationalTableModel::LeftJoin); @@ -448,7 +448,7 @@ void tst_QSqlRelationalTableModel::insertRecord() QSqlRelationalTableModel model(0, db); model.setTable(reltest1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); model.setSort(0, Qt::AscendingOrder); QVERIFY_SQL(model, select()); @@ -498,7 +498,7 @@ void tst_QSqlRelationalTableModel::setRecord() QSqlRelationalTableModel model(0, db); model.setTable(reltest1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); model.setSort(0, Qt::AscendingOrder); QVERIFY_SQL(model, select()); @@ -559,11 +559,11 @@ void tst_QSqlRelationalTableModel::insertWithStrategies() QSqlRelationalTableModel model(0, db); model.setTable(reltest1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); model.setSort(0, Qt::AscendingOrder); if (dbType != QSqlDriver::Sybase) - model.setRelation(3, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(3, QSqlRelation(reltest2, "id", "title")); QVERIFY_SQL(model, select()); QCOMPARE(model.data(model.index(0,0)).toInt(), 1); @@ -667,7 +667,7 @@ void tst_QSqlRelationalTableModel::removeColumn() QSqlRelationalTableModel model(0, db); model.setTable(reltest1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); QVERIFY_SQL(model, select()); QVERIFY_SQL(model, removeColumn(3)); @@ -693,7 +693,7 @@ void tst_QSqlRelationalTableModel::removeColumn() QSqlRelationalTableModel lmodel(0, db); lmodel.setTable(reltest1); - lmodel.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + lmodel.setRelation(2, QSqlRelation(reltest2, "id", "title")); lmodel.setJoinMode(QSqlRelationalTableModel::LeftJoin); QVERIFY_SQL(lmodel, select()); @@ -724,7 +724,7 @@ void tst_QSqlRelationalTableModel::filter() QSqlRelationalTableModel model(0, db); model.setTable(reltest1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); model.setFilter("title = 'herr'"); QVERIFY_SQL(model, select()); @@ -751,9 +751,9 @@ void tst_QSqlRelationalTableModel::sort() QSqlRelationalTableModel model(0, db); model.setTable(reltest1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); if (dbType != QSqlDriver::Sybase) - model.setRelation(3, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(3, QSqlRelation(reltest2, "id", "title")); model.setSort(2, Qt::DescendingOrder); QVERIFY_SQL(model, select()); @@ -879,7 +879,7 @@ void tst_QSqlRelationalTableModel::revert() QSqlRelationalTableModel model(0, db); model.setTable(reltest1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); model.setRelation(3, QSqlRelation(reltest4, "id", "name")); model.setSort(0, Qt::AscendingOrder); @@ -917,10 +917,10 @@ void tst_QSqlRelationalTableModel::clearDisplayValuesCache() QSqlRelationalTableModel model(0, db); model.setTable(reltest1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); if (dbType != QSqlDriver::Sybase) - model.setRelation(3, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(3, QSqlRelation(reltest2, "id", "title")); model.setSort(1, Qt::AscendingOrder); model.setEditStrategy(QSqlTableModel::OnManualSubmit); @@ -1018,7 +1018,7 @@ void tst_QSqlRelationalTableModel::invalidData() QSqlRelationalTableModel model(0, db); model.setTable(reltest1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); QVERIFY_SQL(model, select()); //try set a non-existent relational key @@ -1048,7 +1048,7 @@ void tst_QSqlRelationalTableModel::relationModel() QSqlRelationalTableModel model(0, db); model.setTable(reltest1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); QVERIFY_SQL(model, select()); QVERIFY(!model.relationModel(0)); @@ -1142,7 +1142,7 @@ void tst_QSqlRelationalTableModel::casing() QSqlRelationalTableModel model(0, db); model.setTable(qTableName("CASETEST1", db).toUpper()); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); QVERIFY_SQL(model, select()); QCOMPARE(model.data(model.index(0, 0)).toInt(), 1); @@ -1165,11 +1165,11 @@ void tst_QSqlRelationalTableModel::escapedRelations() //try with relation table name quoted if (dbType == QSqlDriver::Interbase || dbType == QSqlDriver::Oracle || dbType == QSqlDriver::DB2) { model.setRelation(2, QSqlRelation(db.driver()->escapeIdentifier(reltest2.toUpper(),QSqlDriver::TableName), - "tid", + "id", "title")); } else { model.setRelation(2, QSqlRelation(db.driver()->escapeIdentifier(reltest2,QSqlDriver::TableName), - "tid", + "id", "title")); } @@ -1190,11 +1190,11 @@ void tst_QSqlRelationalTableModel::escapedRelations() model.setJoinMode(QSqlRelationalTableModel::InnerJoin); if (dbType == QSqlDriver::Interbase || dbType == QSqlDriver::Oracle || dbType == QSqlDriver::DB2) { model.setRelation(2, QSqlRelation(reltest2, - db.driver()->escapeIdentifier("tid", QSqlDriver::FieldName).toUpper(), + db.driver()->escapeIdentifier("id", QSqlDriver::FieldName).toUpper(), "title")); } else { model.setRelation(2, QSqlRelation(reltest2, - db.driver()->escapeIdentifier("tid", QSqlDriver::FieldName), + db.driver()->escapeIdentifier("id", QSqlDriver::FieldName), "title")); } QVERIFY_SQL(model, select()); @@ -1215,11 +1215,11 @@ void tst_QSqlRelationalTableModel::escapedRelations() if (dbType == QSqlDriver::Interbase || dbType == QSqlDriver::Oracle || dbType == QSqlDriver::DB2) { model.setRelation(2, QSqlRelation(reltest2, - "tid", + "id", db.driver()->escapeIdentifier("title", QSqlDriver::FieldName).toUpper())); } else { model.setRelation(2, QSqlRelation(reltest2, - "tid", + "id", db.driver()->escapeIdentifier("title", QSqlDriver::FieldName))); } @@ -1240,11 +1240,11 @@ void tst_QSqlRelationalTableModel::escapedRelations() model.setJoinMode(QSqlRelationalTableModel::InnerJoin); if (dbType == QSqlDriver::Interbase || dbType == QSqlDriver::Oracle || dbType == QSqlDriver::DB2) { model.setRelation(2, QSqlRelation(reltest2, - "tid", + "id", db.driver()->escapeIdentifier("title", QSqlDriver::FieldName).toUpper())); } else { model.setRelation(2, QSqlRelation(reltest2, - "tid", + "id", db.driver()->escapeIdentifier("title", QSqlDriver::FieldName))); } QVERIFY_SQL(model, select()); @@ -1278,7 +1278,7 @@ void tst_QSqlRelationalTableModel::escapedTableName() model.setTable(db.driver()->escapeIdentifier(reltest1, QSqlDriver::TableName)); } model.setSort(0, Qt::AscendingOrder); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); QVERIFY_SQL(model, select()); QVERIFY(model.setData(model.index(0, 1), QString("harry2"))); @@ -1308,7 +1308,7 @@ void tst_QSqlRelationalTableModel::escapedTableName() QCOMPARE(model.data(model.index(3, 1)).toString(), QString("boris2")); QCOMPARE(model.data(model.index(3, 2)).toInt(), 1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); QVERIFY_SQL(model, select()); QCOMPARE(model.data(model.index(0, 2)).toString(), QString("mister")); QCOMPARE(model.data(model.index(3,2)).toString(), QString("herr")); @@ -1325,7 +1325,7 @@ void tst_QSqlRelationalTableModel::escapedTableName() model.setTable(db.driver()->escapeIdentifier(reltest1, QSqlDriver::TableName)); } model.setSort(0, Qt::AscendingOrder); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); model.setJoinMode(QSqlRelationalTableModel::LeftJoin); QVERIFY_SQL(model, select()); @@ -1357,7 +1357,7 @@ void tst_QSqlRelationalTableModel::escapedTableName() QCOMPARE(model.data(model.index(3, 1)).toString(), QString("boris2")); QCOMPARE(model.data(model.index(3, 2)).toInt(), 1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); QVERIFY_SQL(model, select()); QCOMPARE(model.data(model.index(0, 2)).toString(), QString("mister")); QCOMPARE(model.data(model.index(3,2)).toString(), QString("herr")); @@ -1485,7 +1485,7 @@ void tst_QSqlRelationalTableModel::selectAfterUpdate() QSqlRelationalTableModel model(0, db); model.setTable(reltest1); - model.setRelation(2, QSqlRelation(reltest2, "tid", "title")); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); QVERIFY_SQL(model, select()); QCOMPARE(model.relationModel(2)->rowCount(), 2); { From de82352d288475093a7692d8d998e8d6e9769e0e Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Sun, 14 Feb 2016 02:00:39 -0800 Subject: [PATCH 58/62] Wrap legacy APIs in a QT_MAC_DEPLOYMENT_TARGET_BELOW macro. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the deployment target is OS X >= 10.10 or iOS >= 8.0, we always have the NSProcessInfo API available and do not need to compile-in this code at all. Change-Id: I8470a5be475a82e7b88d62f4558925f62527b6f6 Reviewed-by: Tor Arne Vestbø --- src/corelib/kernel/qcore_mac_objc.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index 798307f8ab4..1a2b0470416 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -107,6 +107,7 @@ QAppleOperatingSystemVersion qt_apple_os_version() // Use temporary variables so we can return 0.0.0 (unknown version) // in case of an error partway through determining the OS version qint32 major = 0, minor = 0, patch = 0; +#if QT_MAC_DEPLOYMENT_TARGET_BELOW(__MAC_10_10, __IPHONE_8_0) #if defined(Q_OS_IOS) @autoreleasepool { NSArray *parts = [UIDevice.currentDevice.systemVersion componentsSeparatedByString:@"."]; @@ -129,6 +130,7 @@ QAppleOperatingSystemVersion qt_apple_os_version() return v; if (pGestalt('sys3', &patch) != 0) return v; +#endif #endif v.major = major; v.minor = minor; From cf47e2e181866ebb364f66da0f5891a418ea808d Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Sun, 14 Feb 2016 02:04:41 -0800 Subject: [PATCH 59/62] Fix build when QMacStyle is disabled. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ica66ab2b48266590b14d16a323b572f63168a580 Reviewed-by: Morten Johan Sørvig Reviewed-by: Tor Arne Vestbø --- src/widgets/styles/qstyleoption.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/styles/qstyleoption.cpp b/src/widgets/styles/qstyleoption.cpp index d66dbec4723..28c0b41a15c 100644 --- a/src/widgets/styles/qstyleoption.cpp +++ b/src/widgets/styles/qstyleoption.cpp @@ -198,7 +198,7 @@ void QStyleOption::init(const QWidget *widget) if (!(state & QStyle::State_Active) && !qt_mac_can_clickThrough(widget)) state &= ~QStyle::State_Enabled; #endif -#if defined(Q_OS_MACX) +#if defined(Q_OS_OSX) && !defined(QT_NO_STYLE_MAC) switch (QMacStyle::widgetSizePolicy(widget)) { case QMacStyle::SizeSmall: state |= QStyle::State_Small; From 6342fb2c3ec516eb5f0fcbd883a65e61acc802de Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 17 Feb 2016 13:27:46 +0100 Subject: [PATCH 60/62] Bump version Change-Id: I62b55dde4a21a46470cafcc0e0b46bc70c097052 Reviewed-by: Simon Hausmann Reviewed-by: Frederik Gladhorn --- .qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qmake.conf b/.qmake.conf index 732b5da2621..53993bd4fe8 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -5,4 +5,4 @@ CONFIG += warning_clean QT_SOURCE_TREE = $$PWD QT_BUILD_TREE = $$shadowed($$PWD) -MODULE_VERSION = 5.6.0 +MODULE_VERSION = 5.6.1 From 03f1a69e9cffe919597373471f7609521a465470 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 18 Mar 2015 08:49:39 +0100 Subject: [PATCH 61/62] Avoid size overflows when inserting into very large JSON objects QJson has a size limitation for arrays and objects. Make sure we don't go over that size limit and create corrupt objects when inserting data. Change-Id: I45be3caefc282d8041f38acd120b985ed4389b8c Reviewed-by: Oswald Buddenhagen Reviewed-by: Simon Hausmann Reviewed-by: Thiago Macieira --- src/corelib/json/qjson_p.h | 6 +++++- src/corelib/json/qjsonarray.cpp | 31 ++++++++++++++++++++++++------ src/corelib/json/qjsonarray.h | 6 ++++-- src/corelib/json/qjsondocument.cpp | 4 ++-- src/corelib/json/qjsonobject.cpp | 29 +++++++++++++++++++++------- src/corelib/json/qjsonobject.h | 6 ++++-- 6 files changed, 62 insertions(+), 20 deletions(-) diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h index 7f5a2d88a1f..1767b3e9e6a 100644 --- a/src/corelib/json/qjson_p.h +++ b/src/corelib/json/qjson_p.h @@ -788,7 +788,11 @@ public: if (reserve) { if (reserve < 128) reserve = 128; - size = qMax(size + reserve, size *2); + size = qMax(size + reserve, qMin(size *2, (int)Value::MaxSize)); + if (size > Value::MaxSize) { + qWarning("QJson: Document too large to store in data structure"); + return 0; + } } char *raw = (char *)malloc(size); Q_CHECK_PTR(raw); diff --git a/src/corelib/json/qjsonarray.cpp b/src/corelib/json/qjsonarray.cpp index bb33dbde747..e8d54b5b879 100644 --- a/src/corelib/json/qjsonarray.cpp +++ b/src/corelib/json/qjsonarray.cpp @@ -382,7 +382,7 @@ void QJsonArray::removeAt(int i) if (!a || i < 0 || i >= (int)a->length) return; - detach(); + detach2(); a->removeItems(i, 1); ++d->compactionCounter; if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(a->length) / 2u) @@ -442,7 +442,8 @@ void QJsonArray::insert(int i, const QJsonValue &value) bool compressed; int valueSize = QJsonPrivate::Value::requiredStorage(val, &compressed); - detach(valueSize + sizeof(QJsonPrivate::Value)); + if (!detach2(valueSize + sizeof(QJsonPrivate::Value))) + return; if (!a->length) a->tableOffset = sizeof(QJsonPrivate::Array); @@ -492,7 +493,8 @@ void QJsonArray::replace(int i, const QJsonValue &value) bool compressed; int valueSize = QJsonPrivate::Value::requiredStorage(val, &compressed); - detach(valueSize); + if (!detach2(valueSize)) + return; if (!a->length) a->tableOffset = sizeof(QJsonPrivate::Array); @@ -1122,22 +1124,39 @@ bool QJsonArray::operator!=(const QJsonArray &other) const \internal */ void QJsonArray::detach(uint reserve) +{ + Q_UNUSED(reserve) + Q_ASSERT(!reserve); + detach2(0); +} + +/*! + \internal + */ +bool QJsonArray::detach2(uint reserve) { if (!d) { + if (reserve >= QJsonPrivate::Value::MaxSize) { + qWarning("QJson: Document too large to store in data structure"); + return false; + } d = new QJsonPrivate::Data(reserve, QJsonValue::Array); a = static_cast(d->header->root()); d->ref.ref(); - return; + return true; } if (reserve == 0 && d->ref.load() == 1) - return; + return true; QJsonPrivate::Data *x = d->clone(a, reserve); + if (!x) + return false; x->ref.ref(); if (!d->ref.deref()) delete d; d = x; a = static_cast(d->header->root()); + return true; } /*! @@ -1148,7 +1167,7 @@ void QJsonArray::compact() if (!d || !d->compactionCounter) return; - detach(); + detach2(); d->compact(); a = static_cast(d->header->root()); } diff --git a/src/corelib/json/qjsonarray.h b/src/corelib/json/qjsonarray.h index 611e1f41933..0f86cfc9881 100644 --- a/src/corelib/json/qjsonarray.h +++ b/src/corelib/json/qjsonarray.h @@ -185,10 +185,10 @@ public: friend class const_iterator; // stl style - inline iterator begin() { detach(); return iterator(this, 0); } + inline iterator begin() { detach2(); return iterator(this, 0); } inline const_iterator begin() const { return const_iterator(this, 0); } inline const_iterator constBegin() const { return const_iterator(this, 0); } - inline iterator end() { detach(); return iterator(this, size()); } + inline iterator end() { detach2(); return iterator(this, size()); } inline const_iterator end() const { return const_iterator(this, size()); } inline const_iterator constEnd() const { return const_iterator(this, size()); } iterator insert(iterator before, const QJsonValue &value) { insert(before.i, value); return before; } @@ -229,7 +229,9 @@ private: QJsonArray(QJsonPrivate::Data *data, QJsonPrivate::Array *array); void initialize(); void compact(); + // ### Qt 6: remove me and merge with detach2 void detach(uint reserve = 0); + bool detach2(uint reserve = 0); QJsonPrivate::Data *d; QJsonPrivate::Array *a; diff --git a/src/corelib/json/qjsondocument.cpp b/src/corelib/json/qjsondocument.cpp index 3ef006d82d2..5f8f807cf0b 100644 --- a/src/corelib/json/qjsondocument.cpp +++ b/src/corelib/json/qjsondocument.cpp @@ -482,7 +482,7 @@ void QJsonDocument::setObject(const QJsonObject &object) if (d->compactionCounter) o.compact(); else - o.detach(); + o.detach2(); d = o.d; d->ref.ref(); return; @@ -509,7 +509,7 @@ void QJsonDocument::setArray(const QJsonArray &array) if (d->compactionCounter) a.compact(); else - a.detach(); + a.detach2(); d = a.d; d->ref.ref(); return; diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp index e43d8111570..8b45dd196be 100644 --- a/src/corelib/json/qjsonobject.cpp +++ b/src/corelib/json/qjsonobject.cpp @@ -389,7 +389,8 @@ QJsonObject::iterator QJsonObject::insert(const QString &key, const QJsonValue & int valueOffset = sizeof(QJsonPrivate::Entry) + QJsonPrivate::qStringSize(key, latinKey); int requiredSize = valueOffset + valueSize; - detach(requiredSize + sizeof(QJsonPrivate::offset)); // offset for the new index entry + if (!detach2(requiredSize + sizeof(QJsonPrivate::offset))) // offset for the new index entry + return iterator(); if (!o->length) o->tableOffset = sizeof(QJsonPrivate::Object); @@ -433,7 +434,7 @@ void QJsonObject::remove(const QString &key) if (!keyExists) return; - detach(); + detach2(); o->removeItems(index, 1); ++d->compactionCounter; if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) @@ -460,7 +461,7 @@ QJsonValue QJsonObject::take(const QString &key) return QJsonValue(QJsonValue::Undefined); QJsonValue v(d, o, o->entryAt(index)->value); - detach(); + detach2(); o->removeItems(index, 1); ++d->compactionCounter; if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) @@ -554,7 +555,7 @@ QJsonObject::iterator QJsonObject::find(const QString &key) int index = o ? o->indexOf(key, &keyExists) : 0; if (!keyExists) return end(); - detach(); + detach2(); return iterator(this, index); } @@ -1060,22 +1061,36 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const \internal */ void QJsonObject::detach(uint reserve) +{ + Q_UNUSED(reserve) + Q_ASSERT(!reserve); + detach2(reserve); +} + +bool QJsonObject::detach2(uint reserve) { if (!d) { + if (reserve >= QJsonPrivate::Value::MaxSize) { + qWarning("QJson: Document too large to store in data structure"); + return false; + } d = new QJsonPrivate::Data(reserve, QJsonValue::Object); o = static_cast(d->header->root()); d->ref.ref(); - return; + return true; } if (reserve == 0 && d->ref.load() == 1) - return; + return true; QJsonPrivate::Data *x = d->clone(o, reserve); + if (!x) + return false; x->ref.ref(); if (!d->ref.deref()) delete d; d = x; o = static_cast(d->header->root()); + return true; } /*! @@ -1086,7 +1101,7 @@ void QJsonObject::compact() if (!d || !d->compactionCounter) return; - detach(); + detach2(); d->compact(); o = static_cast(d->header->root()); } diff --git a/src/corelib/json/qjsonobject.h b/src/corelib/json/qjsonobject.h index 8535da4a6c9..6fb82b7165c 100644 --- a/src/corelib/json/qjsonobject.h +++ b/src/corelib/json/qjsonobject.h @@ -182,10 +182,10 @@ public: friend class const_iterator; // STL style - inline iterator begin() { detach(); return iterator(this, 0); } + inline iterator begin() { detach2(); return iterator(this, 0); } inline const_iterator begin() const { return const_iterator(this, 0); } inline const_iterator constBegin() const { return const_iterator(this, 0); } - inline iterator end() { detach(); return iterator(this, size()); } + inline iterator end() { detach2(); return iterator(this, size()); } inline const_iterator end() const { return const_iterator(this, size()); } inline const_iterator constEnd() const { return const_iterator(this, size()); } iterator erase(iterator it); @@ -215,7 +215,9 @@ private: QJsonObject(QJsonPrivate::Data *data, QJsonPrivate::Object *object); void initialize(); + // ### Qt 6: remove me and merge with detach2 void detach(uint reserve = 0); + bool detach2(uint reserve = 0); void compact(); QString keyAt(int i) const; From 4889269ff0fb37130b332863e82dd7c19564116c Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 18 Mar 2015 08:49:09 +0100 Subject: [PATCH 62/62] Fix quadratic behavior when converting from QVariant The old code called insert for each item, leading to constant reallocation of the data structure. Instead rely on the fact that a QVariantMap (as well as the variant list) is sorted, so we can convert to the QJson data structure in one go without lots of reallocations. Task-number: QTBUG-44737 Change-Id: Id2d38d278fb9afa5e062c7353b4d4215bdfb993c Reviewed-by: Thiago Macieira --- src/corelib/json/qjsonarray.cpp | 41 +++++++++++++++++++++++-- src/corelib/json/qjsonobject.cpp | 51 +++++++++++++++++++++++++++++--- 2 files changed, 86 insertions(+), 6 deletions(-) diff --git a/src/corelib/json/qjsonarray.cpp b/src/corelib/json/qjsonarray.cpp index e8d54b5b879..dc8851e8e7e 100644 --- a/src/corelib/json/qjsonarray.cpp +++ b/src/corelib/json/qjsonarray.cpp @@ -256,8 +256,45 @@ QJsonArray QJsonArray::fromStringList(const QStringList &list) QJsonArray QJsonArray::fromVariantList(const QVariantList &list) { QJsonArray array; - for (QVariantList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it) - array.append(QJsonValue::fromVariant(*it)); + if (list.isEmpty()) + return array; + + array.detach2(1024); + + QVector values; + values.resize(list.size()); + QJsonPrivate::Value *valueData = values.data(); + uint currentOffset = sizeof(QJsonPrivate::Base); + + for (int i = 0; i < list.size(); ++i) { + QJsonValue val = QJsonValue::fromVariant(list.at(i)); + + bool latinOrIntValue; + int valueSize = QJsonPrivate::Value::requiredStorage(val, &latinOrIntValue); + + if (!array.detach2(valueSize)) + return QJsonArray(); + + QJsonPrivate::Value *v = valueData + i; + v->type = (val.t == QJsonValue::Undefined ? QJsonValue::Null : val.t); + v->latinOrIntValue = latinOrIntValue; + v->latinKey = false; + v->value = QJsonPrivate::Value::valueToStore(val, currentOffset); + if (valueSize) + QJsonPrivate::Value::copyData(val, (char *)array.a + currentOffset, latinOrIntValue); + + currentOffset += valueSize; + array.a->size = currentOffset; + } + + // write table + array.a->tableOffset = currentOffset; + if (!array.detach2(sizeof(QJsonPrivate::offset)*values.size())) + return QJsonArray(); + memcpy(array.a->table(), values.constData(), values.size()*sizeof(uint)); + array.a->length = values.size(); + array.a->size = currentOffset + sizeof(QJsonPrivate::offset)*values.size(); + return array; } diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp index 8b45dd196be..b83c8dd19a2 100644 --- a/src/corelib/json/qjsonobject.cpp +++ b/src/corelib/json/qjsonobject.cpp @@ -197,11 +197,54 @@ QJsonObject &QJsonObject::operator =(const QJsonObject &other) */ QJsonObject QJsonObject::fromVariantMap(const QVariantMap &map) { - // ### this is implemented the trivial way, not the most efficient way - QJsonObject object; - for (QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it) - object.insert(it.key(), QJsonValue::fromVariant(it.value())); + if (map.isEmpty()) + return object; + + object.detach2(1024); + + QVector offsets; + QJsonPrivate::offset currentOffset; + currentOffset = sizeof(QJsonPrivate::Base); + + // the map is already sorted, so we can simply append one entry after the other and + // write the offset table at the end + for (QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it) { + QString key = it.key(); + QJsonValue val = QJsonValue::fromVariant(it.value()); + + bool latinOrIntValue; + int valueSize = QJsonPrivate::Value::requiredStorage(val, &latinOrIntValue); + + bool latinKey = QJsonPrivate::useCompressed(key); + int valueOffset = sizeof(QJsonPrivate::Entry) + QJsonPrivate::qStringSize(key, latinKey); + int requiredSize = valueOffset + valueSize; + + if (!object.detach2(requiredSize + sizeof(QJsonPrivate::offset))) // offset for the new index entry + return QJsonObject(); + + QJsonPrivate::Entry *e = reinterpret_cast(reinterpret_cast(object.o) + currentOffset); + e->value.type = val.t; + e->value.latinKey = latinKey; + e->value.latinOrIntValue = latinOrIntValue; + e->value.value = QJsonPrivate::Value::valueToStore(val, (char *)e - (char *)object.o + valueOffset); + QJsonPrivate::copyString((char *)(e + 1), key, latinKey); + if (valueSize) + QJsonPrivate::Value::copyData(val, (char *)e + valueOffset, latinOrIntValue); + + offsets << currentOffset; + currentOffset += requiredSize; + object.o->size = currentOffset; + } + + // write table + object.o->tableOffset = currentOffset; + if (!object.detach2(sizeof(QJsonPrivate::offset)*offsets.size())) + return QJsonObject(); + memcpy(object.o->table(), offsets.constData(), offsets.size()*sizeof(uint)); + object.o->length = offsets.size(); + object.o->size = currentOffset + sizeof(QJsonPrivate::offset)*offsets.size(); + return object; }