From ba7f76dea029bc56288ecb46925f5104c6915a71 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 26 Jan 2016 10:49:31 +0100 Subject: [PATCH 001/118] 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 bc77df566e..882a7a6913 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 31a2124b03..49b289cd79 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 2281bf56cc..9dac667ce5 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 002/118] 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 4dd2ee35b1..de5bec6f93 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 003/118] 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 723c341e59..624220ae5e 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 608a7583c0..f554bbfe90 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 004/118] 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 f554bbfe90..081bf927d9 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 005/118] 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 dfb6c9c471..eb51447105 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 c5462b2936..d42d7a1a70 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 983ff13742..d3cb52d94f 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 e5dcfb2e55..587844c1dd 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 006/118] 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 d9d1c887c1..334b6cd463 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 c45e60ef6e..564dc7f245 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 007/118] 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 fee3146f04..07a1e77c3a 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 008/118] 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 bec94c1e51..034879c478 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 009/118] 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 2e386532e2..7e0973040a 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 07a1e77c3a..83b551557f 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 2086ce56e2..35b27cba0b 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 8301be8c17..84856831c3 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 010/118] 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 65650504ac..9e2a23a7f7 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 5506c96221..78cb06986f 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 011/118] 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 9dc013ba4d..4c1b190b9c 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 012/118] 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 83b551557f..8ec5d20e05 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 013/118] 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 8e40eb6dff..5ac903c71d 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 7e0973040a..c65d69e842 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 a56cea1dfe..3844ca3d0f 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 4d2463b84d..95e2b31405 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 a1d5490845..1b9a66d877 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 014/118] 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 7a38ff8f38..1f04c8b0d7 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 015/118] 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 b04aa7053a..3290cec604 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 016/118] 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 a9dcb8bb7d..4bbc303ac0 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 aa117ed7de..f80a72e2df 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 017/118] 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 e543ea65e6..bb28af975f 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 018/118] 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 1a14500bd4..b3df139743 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 9a53e06730..222562dfce 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 019/118] 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 d6b4a65600..953f669501 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 020/118] 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 5cd0bde87b..ab3f29e2c7 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 021/118] 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 0c579b3e74..7651e295ec 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 9d9815a7b3..7f18bbb721 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 282b6bdfa7..527a94870c 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 68a886ed89..b52be38b4e 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 b930fca78b..11041dee3d 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 48dc4d64fb..b52be38b4e 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 022/118] 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 6a0900cf3f..bc81135d7a 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 bd98cb326c..70b100d018 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 8495b3a320..adbc371fdf 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 841967a545..a658f24ac5 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 a5d5677938..695fc76052 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 5716e3447d..c57453d41f 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 023/118] 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 6f8d97e028..0de0fe21f2 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 024/118] 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 f9ad6c0ac0..0c0653e8ab 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 a6b1d0af26..af9d2a5969 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 c34bea0242..3b04c59e28 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 025/118] 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 5336dfba38..16071df956 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 0f2d799b92..7f44272bc3 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 ebf42b0b06..cd448613d6 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 026/118] 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 ef12b23caa..27bab10196 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 027/118] 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 8a5a6d4fcf..c39675b0b6 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 028/118] 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 5ac903c71d..33d5e76e52 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 029/118] 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 9e33787f53..fac3ae420d 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 4bbc303ac0..e10ddf22a7 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 030/118] 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 bb4f4b1abd..d99a6caecd 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 031/118] 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 0000000000..8496a620b3 --- /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 ee9709e68b..26cace1403 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 fa7c829b30..547a9a2a73 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 4e8745ca78..28e4856056 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 6d3c17f35f..ae0f7bb868 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 7f55c2dae0..14c41711ac 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 717c791280..373343fa22 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 5db5c97917..c8d93585b2 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 78ccbe302a..8d18d40e05 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 0000000000..a10cf663d0 --- /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 de49d5ff45..dbc3e26837 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 032/118] 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 2b42889cb1..7ed268c2d4 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 033/118] 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 7ed268c2d4..4b4d08441f 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 034/118] 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 28c7099d3c..f0e5810b54 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 1ff19f4e04..ff98d186c5 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 05ccff5de0..fb44a7aeb1 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 035/118] 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 27f937e750..e43d811157 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 036/118] 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 0cefa374fa..dee263c664 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 037/118] 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 fd14523d45..21df5d0643 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 038/118] 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 e49a1a098d..27ae07441e 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 039/118] 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 a0474b6710..9228ef8d62 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 040/118] 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 b9e893c650..9f65f73a81 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 20517bc5a9..5983741711 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 4f463dd77c..00f9ecea60 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 bb4f4b1abd..71491595a4 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 eaaf2820ee..a8264b55c0 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 82d67e36f5..2ff71d827b 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 041/118] 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 aea029b7f5..04532e82aa 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 042/118] 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 7ba6b123e8..9c748c0373 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 b254c5a2af..a68425e100 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 a7a9b375ff..8db3bdbc7f 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 7f23656c02..6eb35e1558 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 81525d9dd6..44d07f1624 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 e9ac4a9cc2..fbce78eb74 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 5e648eabf5..757c78cec8 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 97f82d16d3..20039d902a 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 fc66c4ec4c..03ad6a24e9 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 043/118] 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 2bb50ceb71..ea765642e6 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 aa4945f90e..dd846955f6 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 044/118] 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 7b97a03db2..f65ca2048a 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 045/118] 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 5bc9fe3c7f..32e40b9f4d 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 046/118] 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 bf42ca190b..1adf4115c9 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 88ceb37693..823c3e7c7b 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 047/118] 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 f7c1f03c0f..0d43b09d6b 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 f49da1f5a8..95e924bd77 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 048/118] 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 2707b6df41..c2290add5b 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 049/118] 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 237e20685a..899060764f 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 e588f44370..c9b160a8d1 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 050/118] 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 0000000000..4e71490902 --- /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 0000000000..1fb10bdfc0 --- /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 9dac667ce5..30c0e81e21 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 9bf5d27973..1ed286ab2e 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 be6aad02d1..991ec1789b 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 051/118] 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 4517200a2d..fc7ab15f73 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 20b27a3865..b5d9dfed4f 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 793256a83f..22fb8cb63e 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 41619f5bd8..e8495e202f 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 9228ef8d62..72fc378760 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 6f88ff46e6..d5a1a40efc 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 7d09551f5b..7ef13fd0aa 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 2e159cbd55..e1a0e14964 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 034879c478..07904ffbf7 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 9ac7adbf4d..36f5b9de84 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 052/118] 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 9c79509874..a17d89e735 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 5b206af357..3cf9f7fe0b 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 053/118] 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 a77d6743ad..3dedd7d7be 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 054/118] 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 30cbed4aa8..e0d991aaf8 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 055/118] 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 2ca17692db..b0f7adf43a 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 056/118] 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 ca0a8b95d5..7b6be9ebf9 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 f27c8eb1f3..4085ae6b3f 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 057/118] 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 ccfc6e04f0..9ee8d67f56 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 3702631275..7007664c39 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 058/118] 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 798307f8ab..1a2b047041 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 059/118] 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 d66dbec472..28c0b41a15 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 060/118] 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 732b5da262..53993bd4fe 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 061/118] 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 7f5a2d88a1..1767b3e9e6 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 bb33dbde74..e8d54b5b87 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 611e1f4193..0f86cfc988 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 3ef006d82d..5f8f807cf0 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 e43d811157..8b45dd196b 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 8535da4a6c..6fb82b7165 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 062/118] 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 e8d54b5b87..dc8851e8e7 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 8b45dd196b..b83c8dd19a 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; } From 78ad8f208d8dbe3575194bb9b97d4e42efdc32d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Mon, 15 Feb 2016 20:50:16 +0100 Subject: [PATCH 063/118] xcb: Fix drag and drop between xcb screens Set the proper screen before creating a shaped pixmap window in QBasicDrag::startDrag(). Grab mouse again when D&D window is recreated. Task-number: QTBUG-51215 Change-Id: I5cb47d3b11672b56d17b32072d84a722bdcdcd9a Reviewed-by: Friedemann Kleint Reviewed-by: Shawn Rutledge --- src/gui/kernel/qsimpledrag.cpp | 5 +++-- src/gui/kernel/qsimpledrag_p.h | 3 +++ src/plugins/platforms/xcb/qxcbdrag.cpp | 4 ++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp index 9f38c9b78a..00589d2303 100644 --- a/src/gui/kernel/qsimpledrag.cpp +++ b/src/gui/kernel/qsimpledrag.cpp @@ -88,7 +88,8 @@ static QWindow* topLevelAt(const QPoint &pos) QBasicDrag::QBasicDrag() : m_restoreCursor(false), m_eventLoop(0), m_executed_drop_action(Qt::IgnoreAction), m_can_drop(false), - m_drag(0), m_drag_icon_window(0), m_useCompositing(true) + m_drag(0), m_drag_icon_window(0), m_useCompositing(true), + m_screen(Q_NULLPTR) { } @@ -211,7 +212,7 @@ void QBasicDrag::startDrag() pos = QPoint(); } #endif - recreateShapedPixmapWindow(Q_NULLPTR, pos); + recreateShapedPixmapWindow(m_screen, pos); enableEventFilter(); } diff --git a/src/gui/kernel/qsimpledrag_p.h b/src/gui/kernel/qsimpledrag_p.h index 055136c436..b208c8ccc9 100644 --- a/src/gui/kernel/qsimpledrag_p.h +++ b/src/gui/kernel/qsimpledrag_p.h @@ -90,6 +90,8 @@ protected: bool useCompositing() const { return m_useCompositing; } void setUseCompositing(bool on) { m_useCompositing = on; } + void setScreen(QScreen *screen) { m_screen = screen; } + Qt::DropAction executedDropAction() const { return m_executed_drop_action; } void setExecutedDropAction(Qt::DropAction da) { m_executed_drop_action = da; } @@ -108,6 +110,7 @@ private: QDrag *m_drag; QShapedPixmapWindow *m_drag_icon_window; bool m_useCompositing; + QScreen *m_screen; }; class Q_GUI_EXPORT QSimpleDrag : public QBasicDrag diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 9296a6d141..aa6445d2da 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -193,6 +193,7 @@ void QXcbDrag::startDrag() XCB_ATOM_ATOM, 32, drag_types.size(), (const void *)drag_types.constData()); setUseCompositing(current_virtual_desktop->compositingActive()); + setScreen(current_virtual_desktop->screens().constFirst()->screen()); QBasicDrag::startDrag(); if (connection()->mouseGrabber() == Q_NULLPTR) shapedPixmapWindow()->setMouseGrabEnabled(true); @@ -322,6 +323,9 @@ void QXcbDrag::move(const QPoint &globalPos) if (virtualDesktop != current_virtual_desktop) { setUseCompositing(virtualDesktop->compositingActive()); recreateShapedPixmapWindow(static_cast(screen)->screen(), deviceIndependentPos); + if (connection()->mouseGrabber() == Q_NULLPTR) + shapedPixmapWindow()->setMouseGrabEnabled(true); + current_virtual_desktop = virtualDesktop; } else { QBasicDrag::moveShapedPixmapWindow(deviceIndependentPos); From 5d2068b91256465f417548b9b4d7f027296355cf Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 18 Feb 2016 10:23:16 +0100 Subject: [PATCH 064/118] Prospective fix to stabilize tst_QMdiArea::subWindowActivated2()/xcb. Ensure that the window is active (as otherwise QMdiArea::activeSubWindow() returns 0) and add a QTRY_COMPARE. Change-Id: I7edb01d43fd2635864266614ef9a0e844f76edbf Reviewed-by: Frederik Gladhorn --- tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp index e23634c515..aa86e02465 100644 --- a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp +++ b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp @@ -497,9 +497,10 @@ void tst_QMdiArea::subWindowActivated2() spy.clear(); mdiArea.show(); - QVERIFY(QTest::qWaitForWindowExposed(&mdiArea)); + QVERIFY(QTest::qWaitForWindowActive(&mdiArea)); QTRY_COMPARE(spy.count(), 1); - QCOMPARE(mdiArea.activeSubWindow(), activeSubWindow); + QVERIFY(mdiArea.currentSubWindow()); + QTRY_COMPARE(mdiArea.activeSubWindow(), activeSubWindow); spy.clear(); if (qGuiApp->styleHints()->showIsFullScreen()) From bb8f01c6018ff4a0e575b5b128fee76b7fe4cbfb Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 17 Feb 2016 16:07:46 +0100 Subject: [PATCH 065/118] QRasterPaintEngine::penChanged(): Assert on painter state. Task-number: QTBUG-48823 Task-number: QTCREATORBUG-14888 Change-Id: I043a777da6b4e3dfdc58770fb136240a57707cb7 Reviewed-by: Tim Jenssen --- src/gui/painting/qpaintengine_raster.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 9d981dcc2c..f70bef72d8 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -683,6 +683,7 @@ void QRasterPaintEngine::penChanged() qDebug() << "QRasterPaintEngine::penChanged():" << state()->pen; #endif QRasterPaintEngineState *s = state(); + Q_ASSERT(s); s->strokeFlags |= DirtyPen; s->dirty |= DirtyPen; } @@ -2194,6 +2195,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe Q_D(QRasterPaintEngine); QRasterPaintEngineState *s = state(); + Q_ASSERT(s); int sr_l = qFloor(sr.left()); int sr_r = qCeil(sr.right()) - 1; int sr_t = qFloor(sr.top()); @@ -2431,6 +2433,7 @@ void QRasterPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, #endif Q_D(QRasterPaintEngine); QRasterPaintEngineState *s = state(); + Q_ASSERT(s); QImage image; From 8917cdf13b67350d2533335bb06f170b0289bfae Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 18 Feb 2016 13:07:07 +0100 Subject: [PATCH 066/118] Windows QPA/font code: Fix warnings as shown by Qt Creator's Clang based code model. Introduce C++ casts and add some conversions. Where possible, increase const-correctness. Task-number: QTBUG-50804 Change-Id: Idd73730ae83b837c065c8c80f500d5336570f228 Reviewed-by: Joerg Bornemann --- .../windows/qwindowsfontdatabase.cpp | 20 ++-- .../platforms/windows/qwindowsfontengine.cpp | 106 +++++++++--------- 2 files changed, 66 insertions(+), 60 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index 1adf4115c9..322ba0ec27 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -269,10 +269,10 @@ namespace { quint16 nameIds[requiredRecordCount] = { 1, 2, 3, 4, 6 }; int sizeOfHeader = sizeof(NameTable) + sizeof(NameRecord) * requiredRecordCount; - int newFamilyNameSize = newFamilyName.size() * sizeof(quint16); + int newFamilyNameSize = newFamilyName.size() * int(sizeof(quint16)); const QString regularString = QString::fromLatin1("Regular"); - int regularStringSize = regularString.size() * sizeof(quint16); + int regularStringSize = regularString.size() * int(sizeof(quint16)); // Align table size of table to 32 bits (pad with 0) int fullSize = ((sizeOfHeader + newFamilyNameSize + regularStringSize) & ~3) + 4; @@ -792,7 +792,7 @@ static QString getEnglishName(const uchar *table, quint32 bytes) length /= 2; i18n_name.resize(length); - QChar *uc = (QChar *) i18n_name.unicode(); + QChar *uc = const_cast(i18n_name.unicode()); const unsigned char *string = table + string_offset + offset; for (int i = 0; i < length; ++i) uc[i] = getUShort(string + 2*i); @@ -800,10 +800,10 @@ static QString getEnglishName(const uchar *table, quint32 bytes) // Apple Roman i18n_name.resize(length); - QChar *uc = (QChar *) i18n_name.unicode(); + QChar *uc = const_cast(i18n_name.unicode()); const unsigned char *string = table + string_offset + offset; for (int i = 0; i < length; ++i) - uc[i] = QLatin1Char(string[i]); + uc[i] = QLatin1Char(char(string[i])); } } } @@ -1154,8 +1154,9 @@ QT_WARNING_POP DWORD count = 0; QByteArray newFontData = font.data(); - HANDLE fontHandle = AddFontMemResourceEx((void *)newFontData.constData(), newFontData.size(), 0, - &count); + HANDLE fontHandle = + AddFontMemResourceEx(const_cast(newFontData.constData()), + DWORD(newFontData.size()), 0, &count); if (count == 0 && fontHandle != 0) { RemoveFontMemResourceEx(fontHandle); fontHandle = 0; @@ -1373,8 +1374,9 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData, return families; DWORD dummy = 0; - font.handle = AddFontMemResourceEx((void *)fontData.constData(), fontData.size(), 0, - &dummy); + font.handle = + AddFontMemResourceEx(const_cast(fontData.constData()), + DWORD(fontData.size()), 0, &dummy); if (font.handle == 0) return QStringList(); diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp index 00f9ecea60..cda8386ca0 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.cpp +++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp @@ -159,6 +159,12 @@ bool QWindowsFontEngine::hasEbdtTable() const return GetFontData(hdc, MAKE_TAG('E', 'B', 'D', 'T'), 0, 0, 0) != GDI_ERROR; } +static inline QString stringFromOutLineTextMetric(const OUTLINETEXTMETRIC *otm, PSTR offset) +{ + const uchar *p = reinterpret_cast(otm) + quintptr(offset); + return QString::fromWCharArray(reinterpret_cast(p)); +} + void QWindowsFontEngine::getCMap() { ttf = (bool)(tm.tmPitchAndFamily & TMPF_TRUETYPE) || hasCMapTable(); @@ -182,11 +188,12 @@ void QWindowsFontEngine::getCMap() _faceId.index = 0; if(cmap) { OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc); - designToDevice = QFixed((int)otm->otmEMSquare)/QFixed::fromReal(fontDef.pixelSize); - unitsPerEm = otm->otmEMSquare; - x_height = (int)otm->otmsXHeight; - loadKerningPairs(QFixed((int)otm->otmEMSquare)/int(otm->otmTextMetrics.tmHeight)); - _faceId.filename = QFile::encodeName(QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpFullName))); + unitsPerEm = int(otm->otmEMSquare); + const QFixed unitsPerEmF(unitsPerEm); + designToDevice = unitsPerEmF / QFixed::fromReal(fontDef.pixelSize); + x_height = int(otm->otmsXHeight); + loadKerningPairs(unitsPerEmF / int(otm->otmTextMetrics.tmHeight)); + _faceId.filename = QFile::encodeName(stringFromOutLineTextMetric(otm, otm->otmpFullName)); lineWidth = otm->otmsUnderscoreSize; fsType = otm->otmfsType; free(otm); @@ -387,9 +394,9 @@ void QWindowsFontEngine::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::Shape for(int i = 0; i < glyphs->numGlyphs; i++) { unsigned int glyph = glyphs->glyphs[i]; if(int(glyph) >= designAdvancesSize) { - int newSize = (glyph + 256) >> 8 << 8; - designAdvances = q_check_ptr((QFixed *)realloc(designAdvances, - newSize*sizeof(QFixed))); + const int newSize = int(glyph + 256) >> 8 << 8; + designAdvances = reinterpret_cast(realloc(designAdvances, size_t(newSize) * sizeof(QFixed))); + Q_CHECK_PTR(designAdvances); for(int i = designAdvancesSize; i < newSize; ++i) designAdvances[i] = -1000000; designAdvancesSize = newSize; @@ -411,9 +418,9 @@ void QWindowsFontEngine::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::Shape unsigned int glyph = glyphs->glyphs[i]; if (glyph >= widthCacheSize) { - int newSize = (glyph + 256) >> 8 << 8; - widthCache = q_check_ptr((unsigned char *)realloc(widthCache, - newSize*sizeof(QFixed))); + const uint newSize = (glyph + 256) >> 8 << 8; + widthCache = reinterpret_cast(realloc(widthCache, newSize * sizeof(QFixed))); + Q_CHECK_PTR(widthCache); memset(widthCache + widthCacheSize, 0, newSize - widthCacheSize); widthCacheSize = newSize; } @@ -433,7 +440,7 @@ void QWindowsFontEngine::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::Shape ++chrLen; } SIZE size = {0, 0}; - GetTextExtentPoint32(hdc, (wchar_t *)ch, chrLen, &size); + GetTextExtentPoint32(hdc, reinterpret_cast(ch), chrLen, &size); width = size.cx; } else { calculateTTFGlyphWidth(hdc, glyph, width); @@ -441,7 +448,7 @@ void QWindowsFontEngine::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::Shape glyphs->advances[i] = width; // if glyph's within cache range, store it for later if (width > 0 && width < 0x100) - widthCache[glyph] = width; + widthCache[glyph] = uchar(width); } } @@ -482,10 +489,10 @@ bool QWindowsFontEngine::getOutlineMetrics(glyph_t glyph, const QTransform &t, g // results provided when transforming via MAT2 does not // match the glyphs that are drawn using a WorldTransform XFORM xform; - xform.eM11 = t.m11(); - xform.eM12 = t.m12(); - xform.eM21 = t.m21(); - xform.eM22 = t.m22(); + xform.eM11 = FLOAT(t.m11()); + xform.eM12 = FLOAT(t.m12()); + xform.eM21 = FLOAT(t.m21()); + xform.eM22 = FLOAT(t.m22()); xform.eDx = 0; xform.eDy = 0; SetGraphicsMode(hdc, GM_ADVANCED); @@ -507,7 +514,8 @@ bool QWindowsFontEngine::getOutlineMetrics(glyph_t glyph, const QTransform &t, g if (res != GDI_ERROR) { *metrics = glyph_metrics_t(gm.gmptGlyphOrigin.x, -gm.gmptGlyphOrigin.y, - (int)gm.gmBlackBoxX, (int)gm.gmBlackBoxY, gm.gmCellIncX, gm.gmCellIncY); + int(gm.gmBlackBoxX), int(gm.gmBlackBoxY), + gm.gmCellIncX, gm.gmCellIncY); return true; } else { return false; @@ -526,7 +534,7 @@ glyph_metrics_t QWindowsFontEngine::boundingBox(glyph_t glyph, const QTransform if (!ttf && !success) { // Bitmap fonts - wchar_t ch = glyph; + wchar_t ch = wchar_t(glyph); ABCFLOAT abc; GetCharABCWidthsFloat(hdc, ch, ch, &abc); int width = qRound(abc.abcfB); @@ -791,7 +799,7 @@ static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc, return false; // #### obey scale *metric = glyph_metrics_t(gMetric.gmptGlyphOrigin.x, -gMetric.gmptGlyphOrigin.y, - (int)gMetric.gmBlackBoxX, (int)gMetric.gmBlackBoxY, + int(gMetric.gmBlackBoxX), int(gMetric.gmBlackBoxY), gMetric.gmCellIncX, gMetric.gmCellIncY); } #endif @@ -801,17 +809,15 @@ static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc, if (ttf) glyphFormat |= GGO_GLYPH_INDEX; - int bufferSize = GDI_ERROR; - bufferSize = GetGlyphOutline(hdc, glyph, glyphFormat, &gMetric, 0, 0, &mat); - if ((DWORD)bufferSize == GDI_ERROR) { + const DWORD bufferSize = GetGlyphOutline(hdc, glyph, glyphFormat, &gMetric, 0, 0, &mat); + if (bufferSize == GDI_ERROR) return false; - } - void *dataBuffer = new char[bufferSize]; + char *dataBuffer = new char[bufferSize]; DWORD ret = GDI_ERROR; ret = GetGlyphOutline(hdc, glyph, glyphFormat, &gMetric, bufferSize, dataBuffer, &mat); if (ret == GDI_ERROR) { - delete [](char *)dataBuffer; + delete [] dataBuffer; return false; } @@ -824,20 +830,18 @@ static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc, } #endif - int offset = 0; - int headerOffset = 0; - TTPOLYGONHEADER *ttph = 0; + DWORD offset = 0; + DWORD headerOffset = 0; QPointF oset = position.toPointF(); while (headerOffset < bufferSize) { - ttph = (TTPOLYGONHEADER*)((char *)dataBuffer + headerOffset); + const TTPOLYGONHEADER *ttph = reinterpret_cast(dataBuffer + headerOffset); QPointF lastPoint(qt_to_qpointf(ttph->pfxStart, scale)); path->moveTo(lastPoint + oset); offset += sizeof(TTPOLYGONHEADER); - TTPOLYCURVE *curve; - while (offsetcb)) { - curve = (TTPOLYCURVE*)((char*)(dataBuffer) + offset); + while (offset < headerOffset + ttph->cb) { + const TTPOLYCURVE *curve = reinterpret_cast(dataBuffer + offset); switch (curve->wType) { case TT_PRIM_LINE: { for (int i=0; icpfx; ++i) { @@ -882,7 +886,7 @@ static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc, path->closeSubpath(); headerOffset += ttph->cb; } - delete [] (char*)dataBuffer; + delete [] dataBuffer; return true; } @@ -980,15 +984,15 @@ QFontEngine::Properties QWindowsFontEngine::properties() const Properties p; p.emSquare = unitsPerEm; p.italicAngle = otm->otmItalicAngle; - p.postscriptName = QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpFamilyName)).toLatin1(); - p.postscriptName += QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpStyleName)).toLatin1(); - p.postscriptName = QFontEngine::convertToPostscriptFontFamilyName(p.postscriptName); + const QByteArray name = stringFromOutLineTextMetric(otm, otm->otmpFamilyName).toLatin1() + + stringFromOutLineTextMetric(otm, otm->otmpStyleName).toLatin1(); + p.postscriptName = QFontEngine::convertToPostscriptFontFamilyName(name); p.boundingBox = QRectF(otm->otmrcFontBox.left, -otm->otmrcFontBox.top, otm->otmrcFontBox.right - otm->otmrcFontBox.left, otm->otmrcFontBox.top - otm->otmrcFontBox.bottom); p.ascent = otm->otmAscent; p.descent = -otm->otmDescent; - p.leading = (int)otm->otmLineGap; + p.leading = int(otm->otmLineGap); p.capHeight = 0; p.lineWidth = otm->otmsUnderscoreSize; free(otm); @@ -1054,10 +1058,10 @@ QWindowsNativeImage *QWindowsFontEngine::drawGDIGlyph(HFONT font, glyph_t glyph, XFORM xform; if (has_transformation) { - xform.eM11 = t.m11(); - xform.eM12 = t.m12(); - xform.eM21 = t.m21(); - xform.eM22 = t.m22(); + xform.eM11 = FLOAT(t.m11()); + xform.eM12 = FLOAT(t.m12()); + xform.eM21 = FLOAT(t.m21()); + xform.eM22 = FLOAT(t.m22()); xform.eDx = margin; xform.eDy = margin; @@ -1067,7 +1071,7 @@ QWindowsNativeImage *QWindowsFontEngine::drawGDIGlyph(HFONT font, glyph_t glyph, SetWorldTransform(hdc, &xform); HGDIOBJ old_font = SelectObject(hdc, font); - int ggo_options = GGO_METRICS | (ttf ? GGO_GLYPH_INDEX : 0); + const UINT ggo_options = GGO_METRICS | (ttf ? GGO_GLYPH_INDEX : 0); GLYPHMETRICS tgm; MAT2 mat; memset(&mat, 0, sizeof(mat)); @@ -1081,13 +1085,13 @@ QWindowsNativeImage *QWindowsFontEngine::drawGDIGlyph(HFONT font, glyph_t glyph, SelectObject(hdc, old_font); if (result == GDI_ERROR) { - const int errorCode = GetLastError(); + const int errorCode = int(GetLastError()); qErrnoWarning(errorCode, "QWinFontEngine: unable to query transformed glyph metrics (GetGlyphOutline() failed, error %d)...", errorCode); return 0; } - iw = tgm.gmBlackBoxX; - ih = tgm.gmBlackBoxY; + iw = int(tgm.gmBlackBoxX); + ih = int(tgm.gmBlackBoxY); xform.eDx -= tgm.gmptGlyphOrigin.x; xform.eDy += tgm.gmptGlyphOrigin.y; @@ -1124,11 +1128,11 @@ QWindowsNativeImage *QWindowsFontEngine::drawGDIGlyph(HFONT font, glyph_t glyph, if (has_transformation) { SetGraphicsMode(hdc, GM_ADVANCED); SetWorldTransform(hdc, &xform); - ExtTextOut(hdc, 0, 0, options, 0, (LPCWSTR) &glyph, 1, 0); + ExtTextOut(hdc, 0, 0, options, 0, reinterpret_cast(&glyph), 1, 0); } else #endif // !Q_OS_WINCE { - ExtTextOut(hdc, -gx + margin, -gy + margin, options, 0, (LPCWSTR) &glyph, 1, 0); + ExtTextOut(hdc, -gx + margin, -gy + margin, options, 0, reinterpret_cast(&glyph), 1, 0); } SelectObject(hdc, old_font); @@ -1159,7 +1163,7 @@ QImage QWindowsFontEngine::alphaMapForGlyph(glyph_t glyph, const QTransform &xfo QImage::Format mask_format = QWindowsNativeImage::systemFormat(); mask_format = QImage::Format_RGB32; - QWindowsNativeImage *mask = drawGDIGlyph(font, glyph, 0, xform, mask_format); + const QWindowsNativeImage *mask = drawGDIGlyph(font, glyph, 0, xform, mask_format); if (mask == 0) { if (m_fontEngineData->clearTypeEnabled) DeleteObject(font); @@ -1206,11 +1210,11 @@ QImage QWindowsFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed, const QTra UINT contrast; SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &contrast, 0); - SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, (void *) 1000, 0); + SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, reinterpret_cast(quintptr(1000)), 0); int margin = glyphMargin(QFontEngine::Format_A32); QWindowsNativeImage *mask = drawGDIGlyph(font, glyph, margin, t, QImage::Format_RGB32); - SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, (void *) quintptr(contrast), 0); + SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, reinterpret_cast(quintptr(contrast)), 0); if (mask == 0) return QImage(); From 11cd0902e6c8661693f20ceab0d374092c765021 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 18 Feb 2016 16:15:44 +0100 Subject: [PATCH 067/118] Re-enable tst_QTreeView::setSortingEnabled on Windows. The test was made insignificant for Windows in change f3939d943ed132eaf3daead797d961c3ffbc31a5. As the failure is not reproduceable locally, re-enable it. Also split apart the test. Task-number: QTBUG-51149 Change-Id: I6a06bdf2369bc3bdbc73dfe4fa416e9d644f8b01 Reviewed-by: Simon Hausmann --- .../widgets/itemviews/qtreeview/qtreeview.pro | 2 - .../itemviews/qtreeview/tst_qtreeview.cpp | 53 +++++++++---------- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/tests/auto/widgets/itemviews/qtreeview/qtreeview.pro b/tests/auto/widgets/itemviews/qtreeview/qtreeview.pro index e8406dab7b..3abd58e73d 100644 --- a/tests/auto/widgets/itemviews/qtreeview/qtreeview.pro +++ b/tests/auto/widgets/itemviews/qtreeview/qtreeview.pro @@ -4,5 +4,3 @@ QT += widgets testlib QT += widgets-private gui-private core-private SOURCES += tst_qtreeview.cpp HEADERS += ../../../../shared/fakedirmodel.h - -win32: CONFIG += insignificant_test diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp index 033464c9db..ea85c8e057 100644 --- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp +++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp @@ -202,7 +202,8 @@ private slots: void hiddenItems(); void spanningItems(); void rowSizeHint(); - void setSortingEnabled(); + void setSortingEnabledTopLevel(); + void setSortingEnabledChild(); void headerHidden(); void indentation(); @@ -2527,33 +2528,31 @@ void tst_QTreeView::rowSizeHint() //From task 155449 (QTreeWidget has a large width for the first section when sorting //is turned on before items are added) -void tst_QTreeView::setSortingEnabled() -{ - //1st the treeview is a top-level - { - QTreeView view; - QStandardItemModel model(1,1); - view.setModel(&model); - const int size = view.header()->sectionSize(0); - view.setSortingEnabled(true); - model.setColumnCount(3); - //we test that changing the column count doesn't change the 1st column size - QCOMPARE(view.header()->sectionSize(0), size); - } - //then it is no more a top-level - { - QMainWindow win; - QTreeView view; - QStandardItemModel model(1,1); - view.setModel(&model); - win.setCentralWidget(&view); - const int size = view.header()->sectionSize(0); - view.setSortingEnabled(true); - model.setColumnCount(3); - //we test that changing the column count doesn't change the 1st column size - QCOMPARE(view.header()->sectionSize(0), size); - } +void tst_QTreeView::setSortingEnabledTopLevel() +{ + QTreeView view; + QStandardItemModel model(1,1); + view.setModel(&model); + const int size = view.header()->sectionSize(0); + view.setSortingEnabled(true); + model.setColumnCount(3); + //we test that changing the column count doesn't change the 1st column size + QCOMPARE(view.header()->sectionSize(0), size); +} + +void tst_QTreeView::setSortingEnabledChild() +{ + QMainWindow win; + QTreeView view; + QStandardItemModel model(1,1); + view.setModel(&model); + win.setCentralWidget(&view); + const int size = view.header()->sectionSize(0); + view.setSortingEnabled(true); + model.setColumnCount(3); + //we test that changing the column count doesn't change the 1st column size + QCOMPARE(view.header()->sectionSize(0), size); } void tst_QTreeView::headerHidden() From 67ced1d9c443011f1d1e332be2ed1abb2ef22456 Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Thu, 11 Feb 2016 13:54:19 +0100 Subject: [PATCH 068/118] OpenGL: Fix for incorrect GL enum in getter QOpenGLShaderProgram::defaultInnerTessellationLevels() uses the wrong GL enum. This patch fixes it. Change-Id: I2d7ebfad27f7b36d3047d80bfacba65c43c68165 Reviewed-by: Sean Harmer --- src/gui/opengl/qopenglshaderprogram.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp index 9714aa4bec..d567800fbd 100644 --- a/src/gui/opengl/qopenglshaderprogram.cpp +++ b/src/gui/opengl/qopenglshaderprogram.cpp @@ -3386,7 +3386,7 @@ QVector QOpenGLShaderProgram::defaultInnerTessellationLevels() const #if defined(QT_OPENGL_4) Q_D(const QOpenGLShaderProgram); if (d->tessellationFuncs) - d->tessellationFuncs->glGetFloatv(GL_PATCH_DEFAULT_OUTER_LEVEL, tessLevels.data()); + d->tessellationFuncs->glGetFloatv(GL_PATCH_DEFAULT_INNER_LEVEL, tessLevels.data()); #endif return tessLevels; } From fef629cd9191bb73f22c5efb6f943e6b672953c1 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 5 Feb 2016 13:25:13 +0100 Subject: [PATCH 069/118] Disable unneeded ligatures when letter spacing is set For writing systems where glyph substitutions are purely cosmetic, we should disable them when letter spacing is set, otherwise we get ligatures where the spacing is not applied. To avoid changing Harfbuzz-NG upstream, we detect this case when fetching the GSUB table and return an empty blob instead. Task-number: QTBUG-44393 Change-Id: Ie5f6b2d795d7fecbba0ece3941fb70ba7f04c395 Reviewed-by: Lars Knoll Reviewed-by: Simon Hausmann --- src/gui/text/qharfbuzzng.cpp | 15 ++++++++++++++- src/gui/text/qharfbuzzng_p.h | 3 +++ src/gui/text/qtextengine.cpp | 19 ++++++++++++++++--- src/gui/text/qtextengine_p.h | 8 +++++++- 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp index b2edfc00a0..6437465da8 100644 --- a/src/gui/text/qharfbuzzng.cpp +++ b/src/gui/text/qharfbuzzng.cpp @@ -573,17 +573,27 @@ _hb_qt_font_get_glyph_from_name(hb_font_t * /*font*/, void * /*font_data*/, static hb_user_data_key_t _useDesignMetricsKey; +static hb_user_data_key_t _ignoreGSUB; void hb_qt_font_set_use_design_metrics(hb_font_t *font, uint value) { hb_font_set_user_data(font, &_useDesignMetricsKey, (void *)quintptr(value), NULL, true); } +void hb_qt_face_set_ignore_gsub(hb_face_t *face, uint value) +{ + hb_face_set_user_data(face, &_ignoreGSUB, (void *)quintptr(value), NULL, true); +} + uint hb_qt_font_get_use_design_metrics(hb_font_t *font) { return quintptr(hb_font_get_user_data(font, &_useDesignMetricsKey)); } +uint hb_qt_face_get_ignore_gsub(hb_face_t *face) +{ + return quintptr(hb_face_get_user_data(face, &_ignoreGSUB)); +} struct _hb_qt_font_funcs_t { _hb_qt_font_funcs_t() @@ -618,11 +628,14 @@ hb_font_funcs_t *hb_qt_get_font_funcs() static hb_blob_t * -_hb_qt_reference_table(hb_face_t * /*face*/, hb_tag_t tag, void *user_data) +_hb_qt_reference_table(hb_face_t *face, hb_tag_t tag, void *user_data) { QFontEngine::FaceData *data = static_cast(user_data); Q_ASSERT(data); + if (hb_qt_face_get_ignore_gsub(face) && tag == HB_TAG('G','S','U','B')) + return hb_blob_get_empty(); + qt_get_font_table_func_t get_font_table = data->get_font_table; Q_ASSERT(get_font_table); diff --git a/src/gui/text/qharfbuzzng_p.h b/src/gui/text/qharfbuzzng_p.h index d5e11e6264..8beadbc72c 100644 --- a/src/gui/text/qharfbuzzng_p.h +++ b/src/gui/text/qharfbuzzng_p.h @@ -72,6 +72,9 @@ Q_GUI_EXPORT hb_font_t *hb_qt_font_get_for_engine(QFontEngine *fe); Q_GUI_EXPORT void hb_qt_font_set_use_design_metrics(hb_font_t *font, uint value); Q_GUI_EXPORT uint hb_qt_font_get_use_design_metrics(hb_font_t *font); +Q_GUI_EXPORT void hb_qt_face_set_ignore_gsub(hb_face_t *font, uint value); +Q_GUI_EXPORT uint hb_qt_face_get_ignore_gsub(hb_face_t *font); + QT_END_NAMESPACE #endif // QHARFBUZZNG_P_H diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 1c924175e2..7dc8e8fadb 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1059,7 +1059,7 @@ void QTextEngine::shapeText(int item) const #ifdef QT_ENABLE_HARFBUZZ_NG if (Q_LIKELY(qt_useHarfbuzzNG())) - si.num_glyphs = shapeTextWithHarfbuzzNG(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled); + si.num_glyphs = shapeTextWithHarfbuzzNG(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled, letterSpacing != 0); else #endif si.num_glyphs = shapeTextWithHarfbuzz(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled); @@ -1121,7 +1121,13 @@ QT_BEGIN_INCLUDE_NAMESPACE QT_END_INCLUDE_NAMESPACE -int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector &itemBoundaries, bool kerningEnabled) const +int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, + const ushort *string, + int itemLength, + QFontEngine *fontEngine, + const QVector &itemBoundaries, + bool kerningEnabled, + bool hasLetterSpacing) const { uint glyphs_shaped = 0; @@ -1135,7 +1141,8 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st hb_segment_properties_t props = HB_SEGMENT_PROPERTIES_DEFAULT; props.direction = si.analysis.bidiLevel % 2 ? HB_DIRECTION_RTL : HB_DIRECTION_LTR; - props.script = hb_qt_script_to_script(QChar::Script(si.analysis.script)); + QChar::Script script = QChar::Script(si.analysis.script); + props.script = hb_qt_script_to_script(script); // ### props.language = hb_language_get_default_for_script(props.script); for (int k = 0; k < itemBoundaries.size(); k += 3) { @@ -1168,6 +1175,12 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st Q_ASSERT(hb_font); hb_qt_font_set_use_design_metrics(hb_font, option.useDesignMetrics() ? uint(QFontEngine::DesignMetrics) : 0); // ### + bool scriptRequiresOpenType = ((script >= QChar::Script_Syriac && script <= QChar::Script_Sinhala) + || script == QChar::Script_Khmer || script == QChar::Script_Nko); + hb_face_t *hb_face = hb_font_get_face(hb_font); + Q_ASSERT(hb_face); + hb_qt_face_set_ignore_gsub(hb_face, hasLetterSpacing && !scriptRequiresOpenType); + const hb_feature_t features[1] = { { HB_TAG('k','e','r','n'), !!kerningEnabled, 0, uint(-1) } }; diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 39c228fd52..7e507bba2d 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -643,7 +643,13 @@ private: void addRequiredBoundaries() const; void shapeText(int item) const; #ifdef QT_ENABLE_HARFBUZZ_NG - int shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector &itemBoundaries, bool kerningEnabled) const; + int shapeTextWithHarfbuzzNG(const QScriptItem &si, + const ushort *string, + int itemLength, + QFontEngine *fontEngine, + const QVector &itemBoundaries, + bool kerningEnabled, + bool hasLetterSpacing) const; #endif int shapeTextWithHarfbuzz(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector &itemBoundaries, bool kerningEnabled) const; From 342c909b340cb1bfbb95480fc79dcea21a470c83 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 3 Feb 2016 13:53:44 +0100 Subject: [PATCH 070/118] Qt Quick: Fix selection when mixing line breaks and line wraps The enabler for finding selection ranges in Qt Quick had two bugs which caused some selected text to disappear. Specifically, this was the case for selected text where a line contained both an explicit break and a break due to line wrapping. First of all, the glyphsEnd that is passed into glyphRunsWithInfo() is expected to be inclusive, since we are actually searching for its index in the log cluster array. We would in certain cases not find the glyph at all in the log clusters, thus the glyph run would be set to overlap with any glyph run coming after it in the same item. Second of all, we need to start searching at the correct position in the log clusters when searching for the correct rangeStart, since rangeStart is initialized with textPosition. Otherwise, we would in some cases never reach the start of the range, and rangeStart would be set to textPosition + textLength, which is the end of the range. Task-number: QTBUG-49596 Change-Id: I436ba3f1c7414d4f5044d9b70aa04c60b01755e4 Reviewed-by: Simon Hausmann --- src/gui/text/qtextlayout.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 9e2a23a7f7..bc9c452ff7 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -2141,6 +2141,7 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, QGlyphRunPrivate *d = QGlyphRunPrivate::get(glyphRun); int rangeStart = textPosition; + logClusters += textPosition; while (*logClusters != glyphsStart && rangeStart < textPosition + textLength) { ++logClusters; ++rangeStart; @@ -2325,16 +2326,16 @@ QList QTextLine::glyphRuns(int from, int length) const if (mainFontEngine->type() == QFontEngine::Multi) { QFontEngineMulti *multiFontEngine = static_cast(mainFontEngine); - int end = rtl ? glyphLayout.numGlyphs : 0; - int start = rtl ? end : 0; - int which = glyphLayout.glyphs[rtl ? start - 1 : end] >> 24; - for (; (rtl && start > 0) || (!rtl && end < glyphLayout.numGlyphs); + int start = rtl ? glyphLayout.numGlyphs : 0; + int end = start - 1; + int which = glyphLayout.glyphs[rtl ? start - 1 : end + 1] >> 24; + for (; (rtl && start > 0) || (!rtl && end < glyphLayout.numGlyphs - 1); rtl ? --start : ++end) { - const int e = glyphLayout.glyphs[rtl ? start - 1 : end] >> 24; + const int e = glyphLayout.glyphs[rtl ? start - 1 : end + 1] >> 24; if (e == which) continue; - QGlyphLayout subLayout = glyphLayout.mid(start, end - start); + QGlyphLayout subLayout = glyphLayout.mid(start, end - start + 1); multiFontEngine->ensureEngineAt(which); QGlyphRun::GlyphRunFlags subFlags = flags; @@ -2358,13 +2359,13 @@ QList QTextLine::glyphRuns(int from, int length) const } if (rtl) - end = start; + end = start - 1; else - start = end; + start = end + 1; which = e; } - QGlyphLayout subLayout = glyphLayout.mid(start, end - start); + QGlyphLayout subLayout = glyphLayout.mid(start, end - start + 1); multiFontEngine->ensureEngineAt(which); QGlyphRun::GlyphRunFlags subFlags = flags; From b20548f9999d8c111268f3f2287c0801c6c5cbb0 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 18 Feb 2016 13:13:49 +0100 Subject: [PATCH 071/118] Windows QPA: Fix warnings as shown by Qt Creator's Clang based code model. Code except font, accessibility and file qwindowswindow.cpp. Task-number: QTBUG-50804 Change-Id: I40848264f9fa16eea00cf70d7be009c484c49e92 Reviewed-by: Oliver Wolff --- .../windows/qwindowsbackingstore.cpp | 4 +- .../platforms/windows/qwindowsclipboard.cpp | 4 +- .../platforms/windows/qwindowscontext.cpp | 46 +++--- .../platforms/windows/qwindowscursor.cpp | 6 +- .../platforms/windows/qwindowsdrag.cpp | 4 +- .../platforms/windows/qwindowseglcontext.cpp | 12 +- .../platforms/windows/qwindowsglcontext.cpp | 6 +- .../windows/qwindowsinputcontext.cpp | 25 +-- .../platforms/windows/qwindowsintegration.cpp | 4 +- .../platforms/windows/qwindowskeymapper.cpp | 66 ++++---- .../platforms/windows/qwindowsmime.cpp | 152 +++++++++--------- .../windows/qwindowsmousehandler.cpp | 20 +-- .../platforms/windows/qwindowsnativeimage.cpp | 8 +- src/plugins/platforms/windows/qwindowsole.cpp | 12 +- src/plugins/platforms/windows/qwindowsole.h | 2 +- .../windows/qwindowsopengltester.cpp | 15 +- .../platforms/windows/qwindowsopengltester.h | 8 +- .../platforms/windows/qwindowsscreen.cpp | 6 +- .../platforms/windows/qwindowsservices.cpp | 10 +- .../windows/qwindowstabletsupport.cpp | 2 +- .../platforms/windows/qwindowstabletsupport.h | 2 +- .../platforms/windows/qwindowstheme.cpp | 11 +- 22 files changed, 214 insertions(+), 211 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp index af9d2a5969..a518c0bb83 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp +++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp @@ -93,7 +93,7 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion ®ion, SIZE size = {r.width(), r.height()}; POINT ptDst = {r.x(), r.y()}; POINT ptSrc = {0, 0}; - BLENDFUNCTION blend = {AC_SRC_OVER, 0, (BYTE)(255.0 * rw->opacity()), AC_SRC_ALPHA}; + BLENDFUNCTION blend = {AC_SRC_OVER, 0, BYTE(qRound(255.0 * rw->opacity())), AC_SRC_ALPHA}; if (QWindowsContext::user32dll.updateLayeredWindowIndirect) { RECT dirty = {dirtyRect.x(), dirtyRect.y(), dirtyRect.x() + dirtyRect.width(), dirtyRect.y() + dirtyRect.height()}; @@ -119,7 +119,7 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion ®ion, m_image->hdc(), br.x() + offset.x(), br.y() + offset.y(), SRCCOPY)) { const DWORD lastError = GetLastError(); // QTBUG-35926, QTBUG-29716: may fail after lock screen. if (lastError != ERROR_SUCCESS && lastError != ERROR_INVALID_HANDLE) - qErrnoWarning(lastError, "%s: BitBlt failed", __FUNCTION__); + qErrnoWarning(int(lastError), "%s: BitBlt failed", __FUNCTION__); } rw->releaseDC(); #ifndef Q_OS_WINCE diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp index 8b0be5d916..930f901523 100644 --- a/src/plugins/platforms/windows/qwindowsclipboard.cpp +++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp @@ -259,9 +259,9 @@ bool QWindowsClipboard::clipboardViewerWndProc(HWND hwnd, UINT message, WPARAM w switch (message) { case WM_CHANGECBCHAIN: { - const HWND toBeRemoved = (HWND)wParam; + const HWND toBeRemoved = reinterpret_cast(wParam); if (toBeRemoved == m_nextClipboardViewer) { - m_nextClipboardViewer = (HWND)lParam; + m_nextClipboardViewer = reinterpret_cast(lParam); } else { propagateClipboardMessage(message, wParam, lParam); } diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 6ff6875c49..09c2f7df2e 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -101,10 +101,10 @@ static inline bool useRTL_Extensions(QSysInfo::WinVersion ver) if ((ver & QSysInfo::WV_NT_based) && (ver >= QSysInfo::WV_VISTA)) { // Since the IsValidLanguageGroup/IsValidLocale functions always return true on // Vista, check the Keyboard Layouts for enabling RTL. - if (const UINT nLayouts = GetKeyboardLayoutList(0, 0)) { + if (const int nLayouts = GetKeyboardLayoutList(0, 0)) { QScopedArrayPointer lpList(new HKL[nLayouts]); GetKeyboardLayoutList(nLayouts, lpList.data()); - for (UINT i = 0; i < nLayouts; ++i) { + for (int i = 0; i < nLayouts; ++i) { switch (PRIMARYLANGID((quintptr)lpList[i])) { case LANG_ARABIC: case LANG_HEBREW: @@ -540,15 +540,15 @@ QString QWindowsContext::registerWindowClass(QString cname, // add an instance-specific ID, the address of the window proc. static int classExists = -1; - const HINSTANCE appInstance = (HINSTANCE)GetModuleHandle(0); + const HINSTANCE appInstance = static_cast(GetModuleHandle(0)); if (classExists == -1) { WNDCLASS wcinfo; - classExists = GetClassInfo(appInstance, (wchar_t*)cname.utf16(), &wcinfo); + classExists = GetClassInfo(appInstance, reinterpret_cast(cname.utf16()), &wcinfo); classExists = classExists && wcinfo.lpfnWndProc != proc; } if (classExists) - cname += QString::number((quintptr)proc); + cname += QString::number(reinterpret_cast(proc)); if (d->m_registeredWindowClassNames.contains(cname)) // already registered in our list return cname; @@ -568,13 +568,13 @@ QString QWindowsContext::registerWindowClass(QString cname, #ifndef Q_OS_WINCE wc.hbrBackground = brush; if (icon) { - wc.hIcon = (HICON)LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); + wc.hIcon = static_cast(LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE)); if (wc.hIcon) { int sw = GetSystemMetrics(SM_CXSMICON); int sh = GetSystemMetrics(SM_CYSMICON); - wc.hIconSm = (HICON)LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, sw, sh, 0); + wc.hIconSm = static_cast(LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, sw, sh, 0)); } else { - wc.hIcon = (HICON)LoadImage(0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + wc.hIcon = static_cast(LoadImage(0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED)); wc.hIconSm = 0; } } else { @@ -590,7 +590,7 @@ QString QWindowsContext::registerWindowClass(QString cname, #endif wc.lpszMenuName = 0; - wc.lpszClassName = (wchar_t*)cname.utf16(); + wc.lpszClassName = reinterpret_cast(cname.utf16()); #ifndef Q_OS_WINCE ATOM atom = RegisterClassEx(&wc); #else @@ -610,10 +610,10 @@ QString QWindowsContext::registerWindowClass(QString cname, void QWindowsContext::unregisterWindowClasses() { - const HINSTANCE appInstance = (HINSTANCE)GetModuleHandle(0); + const HINSTANCE appInstance = static_cast(GetModuleHandle(0)); foreach (const QString &name, d->m_registeredWindowClassNames) { - if (!UnregisterClass((wchar_t*)name.utf16(), appInstance) && QWindowsContext::verbose) + if (!UnregisterClass(reinterpret_cast(name.utf16()), appInstance) && QWindowsContext::verbose) qErrnoWarning("UnregisterClass failed for '%s'", qPrintable(name)); } d->m_registeredWindowClassNames.clear(); @@ -629,11 +629,11 @@ QString QWindowsContext::windowsErrorMessage(unsigned long errorCode) QString rc = QString::fromLatin1("#%1: ").arg(errorCode); ushort *lpMsgBuf; - const int len = FormatMessage( + const DWORD len = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, errorCode, 0, (LPTSTR)&lpMsgBuf, 0, NULL); + NULL, errorCode, 0, reinterpret_cast(&lpMsgBuf), 0, NULL); if (len) { - rc = QString::fromUtf16(lpMsgBuf, len); + rc = QString::fromUtf16(lpMsgBuf, int(len)); LocalFree(lpMsgBuf); } else { rc += QString::fromLatin1(""); @@ -797,11 +797,11 @@ HWND QWindowsContext::createDummyWindow(const QString &classNameIn, if (!wndProc) wndProc = DefWindowProc; QString className = registerWindowClass(classNameIn, wndProc); - return CreateWindowEx(0, (wchar_t*)className.utf16(), + return CreateWindowEx(0, reinterpret_cast(className.utf16()), windowName, style, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - HWND_MESSAGE, NULL, (HINSTANCE)GetModuleHandle(0), NULL); + HWND_MESSAGE, NULL, static_cast(GetModuleHandle(0)), NULL); } #ifndef Q_OS_WINCE @@ -812,11 +812,11 @@ static inline QString errorMessageFromComError(const _com_error &comError) { TCHAR *message = Q_NULLPTR; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, comError.Error(), MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), + NULL, DWORD(comError.Error()), MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), message, 0, NULL); if (message) { const QString result = QString::fromWCharArray(message).trimmed(); - LocalFree((HLOCAL)message); + LocalFree(static_cast(message)); return result; } if (const WORD wCode = comError.WCode()) @@ -1064,7 +1064,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, platformWindow->handleMoved(); return true; case QtWindows::ResizeEvent: - platformWindow->handleResized((int)wParam); + platformWindow->handleResized(static_cast(wParam)); return true; #ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO case QtWindows::QuerySizeHints: @@ -1203,7 +1203,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, sessionManager->setActive(false); sessionManager->allowsInteraction(); - bool endsession = (bool) wParam; + const bool endsession = wParam != 0; // we receive the message for each toplevel window included internal hidden ones, // but the aboutToQuit signal should be emitted only once. @@ -1270,7 +1270,7 @@ bool QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg) bool mouseTriggered = false; QPoint globalPos; QPoint pos; - if (msg.lParam != (int)0xffffffff) { + if (msg.lParam != int(0xffffffff)) { mouseTriggered = true; globalPos.setX(msg.pt.x); globalPos.setY(msg.pt.y); @@ -1278,8 +1278,8 @@ bool QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg) RECT clientRect; if (GetClientRect(msg.hwnd, &clientRect)) { - if (pos.x() < (int)clientRect.left || pos.x() >= (int)clientRect.right || - pos.y() < (int)clientRect.top || pos.y() >= (int)clientRect.bottom) + if (pos.x() < clientRect.left || pos.x() >= clientRect.right || + pos.y() < clientRect.top || pos.y() >= clientRect.bottom) { // This is the case that user has right clicked in the window's caption, // We should call DefWindowProc() to display a default shortcut menu diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index 9f65f73a81..cda741c226 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -113,8 +113,8 @@ HCURSOR QWindowsCursor::createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot ICONINFO ii; ii.fIcon = 0; - ii.xHotspot = hotSpot.x(); - ii.yHotspot = hotSpot.y(); + ii.xHotspot = DWORD(hotSpot.x()); + ii.yHotspot = DWORD(hotSpot.y()); ii.hbmMask = im; ii.hbmColor = ic; @@ -571,7 +571,7 @@ HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape, const for (const QWindowsStandardCursorMapping *s = standardCursors; s < sEnd; ++s) { if (s->shape == cursorShape) { #ifndef Q_OS_WINCE - return (HCURSOR)LoadImage(0, s->resource, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + return static_cast(LoadImage(0, s->resource, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED)); #else return LoadCursor(0, s->resource); #endif diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index 18e67ff1a3..150e135604 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -641,7 +641,7 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState, m_chosenEffect = DROPEFFECT_COPY; HGLOBAL hData = GlobalAlloc(0, sizeof(DWORD)); if (hData) { - DWORD *moveEffect = (DWORD *)GlobalLock(hData);; + DWORD *moveEffect = reinterpret_cast(GlobalLock(hData)); *moveEffect = DROPEFFECT_MOVE; GlobalUnlock(hData); STGMEDIUM medium; @@ -649,7 +649,7 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState, medium.tymed = TYMED_HGLOBAL; medium.hGlobal = hData; FORMATETC format; - format.cfFormat = RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT); + format.cfFormat = CLIPFORMAT(RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT)); format.tymed = TYMED_HGLOBAL; format.ptd = 0; format.dwAspect = 1; diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 5983741711..787a072a7a 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -187,9 +187,9 @@ bool QWindowsLibGLESv2::init() qCDebug(lcQpaGl) << "Qt: Using OpenGL ES 2.0 from" << dllName; #if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC) - m_lib = ::LoadLibraryW((const wchar_t *) QString::fromLatin1(dllName).utf16()); + m_lib = ::LoadLibraryW(reinterpret_cast(QString::fromLatin1(dllName).utf16())); if (!m_lib) { - qErrnoWarning(::GetLastError(), "Failed to load %s", dllName); + qErrnoWarning(int(GetLastError()), "Failed to load %s", dllName); return false; } #endif // !QT_STATIC @@ -395,7 +395,7 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester: Q_UNUSED(preferredType) #endif if (display == EGL_NO_DISPLAY) - display = libEGL.eglGetDisplay((EGLNativeDisplayType)dc); + display = libEGL.eglGetDisplay(dc); if (!display) { qWarning("%s: Could not obtain EGL display", __FUNCTION__); return 0; @@ -427,8 +427,8 @@ QWindowsOpenGLContext *QWindowsEGLStaticContext::createContext(QOpenGLContext *c void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *nativeConfig, int *err) { *err = 0; - EGLSurface surface = libEGL.eglCreateWindowSurface(m_display, (EGLConfig) nativeConfig, - (EGLNativeWindowType) nativeWindow, 0); + EGLSurface surface = libEGL.eglCreateWindowSurface(m_display, nativeConfig, + static_cast(nativeWindow), 0); if (surface == EGL_NO_SURFACE) { *err = libEGL.eglGetError(); qWarning("%s: Could not create the EGL window surface: 0x%x", __FUNCTION__, *err); @@ -439,7 +439,7 @@ void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *na void QWindowsEGLStaticContext::destroyWindowSurface(void *nativeSurface) { - libEGL.eglDestroySurface(m_display, (EGLSurface) nativeSurface); + libEGL.eglDestroySurface(m_display, nativeSurface); } QSurfaceFormat QWindowsEGLStaticContext::formatFromConfig(EGLDisplay display, EGLConfig config, diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index 8d33e2f0db..2eaae6b726 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -1011,7 +1011,7 @@ QOpenGLStaticContext::QOpenGLStaticContext() : QByteArray QOpenGLStaticContext::getGlString(unsigned int which) { if (const GLubyte *s = opengl32.glGetString(which)) - return QByteArray((const char*)s); + return QByteArray(reinterpret_cast(s)); return QByteArray(); } @@ -1238,7 +1238,7 @@ bool QWindowsGLContext::updateObtainedParams(HDC hdc, int *obtainedSwapInterval) bool hasRobustness = false; if (m_obtainedFormat.majorVersion() < 3) { - const char *exts = (const char *) QOpenGLStaticContext::opengl32.glGetString(GL_EXTENSIONS); + const char *exts = reinterpret_cast(QOpenGLStaticContext::opengl32.glGetString(GL_EXTENSIONS)); hasRobustness = exts && strstr(exts, "GL_ARB_robustness"); } else { typedef const GLubyte * (APIENTRY *glGetStringi_t)(GLenum, GLuint); @@ -1247,7 +1247,7 @@ bool QWindowsGLContext::updateObtainedParams(HDC hdc, int *obtainedSwapInterval) GLint n = 0; QOpenGLStaticContext::opengl32.glGetIntegerv(GL_NUM_EXTENSIONS, &n); for (GLint i = 0; i < n; ++i) { - const char *p = (const char *) glGetStringi(GL_EXTENSIONS, i); + const char *p = reinterpret_cast(glGetStringi(GL_EXTENSIONS, i)); if (p && !strcmp(p, "GL_ARB_robustness")) { hasRobustness = true; break; diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index 56b5561756..d3299db460 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -319,7 +319,9 @@ void QWindowsInputContext::invokeAction(QInputMethod::Action action, int cursorP // position. const HIMC himc = ImmGetContext(m_compositionContext.hwnd); const HWND imeWindow = ImmGetDefaultIMEWnd(m_compositionContext.hwnd); - SendMessage(imeWindow, m_WM_MSIME_MOUSE, MAKELONG(MAKEWORD(MK_LBUTTON, cursorPosition == 0 ? 2 : 1), cursorPosition), (LPARAM)himc); + const WPARAM mouseOperationCode = + MAKELONG(MAKEWORD(MK_LBUTTON, cursorPosition == 0 ? 2 : 1), cursorPosition); + SendMessage(imeWindow, m_WM_MSIME_MOUSE, mouseOperationCode, LPARAM(himc)); ImmReleaseContext(m_compositionContext.hwnd, himc); } @@ -328,7 +330,7 @@ static inline QString getCompositionString(HIMC himc, DWORD dwIndex) enum { bufferSize = 256 }; wchar_t buffer[bufferSize]; const int length = ImmGetCompositionString(himc, dwIndex, buffer, bufferSize * sizeof(wchar_t)); - return QString::fromWCharArray(buffer, length / sizeof(wchar_t)); + return QString::fromWCharArray(buffer, size_t(length) / sizeof(wchar_t)); } // Determine the converted string range as pair of start/length to be selected. @@ -559,9 +561,8 @@ bool QWindowsInputContext::handleIME_Request(WPARAM wParam, if (size < 0) return false; *result = size; - return true; } - break; + return true; case IMR_CONFIRMRECONVERTSTRING: return true; default: @@ -572,7 +573,7 @@ bool QWindowsInputContext::handleIME_Request(WPARAM wParam, void QWindowsInputContext::handleInputLanguageChanged(WPARAM wparam, LPARAM lparam) { - const LCID newLanguageId = languageIdFromLocaleId(lparam); + const LCID newLanguageId = languageIdFromLocaleId(WORD(lparam)); if (newLanguageId == m_languageId) return; const LCID oldLanguageId = m_languageId; @@ -606,13 +607,13 @@ int QWindowsInputContext::reconvertString(RECONVERTSTRING *reconv) if (!surroundingTextV.isValid()) return -1; const QString surroundingText = surroundingTextV.toString(); - const DWORD memSize = sizeof(RECONVERTSTRING) - + (surroundingText.length() + 1) * sizeof(ushort); + const int memSize = int(sizeof(RECONVERTSTRING)) + + (surroundingText.length() + 1) * int(sizeof(ushort)); qCDebug(lcQpaInputMethods) << __FUNCTION__ << " reconv=" << reconv << " surroundingText=" << surroundingText << " size=" << memSize; // If memory is not allocated, return the required size. if (!reconv) - return surroundingText.isEmpty() ? -1 : int(memSize); + return surroundingText.isEmpty() ? -1 : memSize; const QVariant posV = QInputMethod::queryFocusObject(Qt::ImCursorPosition, QVariant()); const int pos = posV.isValid() ? posV.toInt() : 0; @@ -631,13 +632,13 @@ int QWindowsInputContext::reconvertString(RECONVERTSTRING *reconv) QInputMethodEvent selectEvent(QString(), attributes); QCoreApplication::sendEvent(fo, &selectEvent); - reconv->dwSize = memSize; + reconv->dwSize = DWORD(memSize); reconv->dwVersion = 0; - reconv->dwStrLen = surroundingText.size(); + reconv->dwStrLen = DWORD(surroundingText.size()); reconv->dwStrOffset = sizeof(RECONVERTSTRING); - reconv->dwCompStrLen = endPos - startPos; // TCHAR count. - reconv->dwCompStrOffset = startPos * sizeof(ushort); // byte count. + reconv->dwCompStrLen = DWORD(endPos - startPos); // TCHAR count. + reconv->dwCompStrOffset = DWORD(startPos) * sizeof(ushort); // byte count. reconv->dwTargetStrLen = reconv->dwCompStrLen; reconv->dwTargetStrOffset = reconv->dwCompStrOffset; ushort *pastReconv = reinterpret_cast(reconv + 1); diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index bd2014b8f2..27ec258f37 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -514,8 +514,8 @@ QVariant QWindowsIntegration::styleHint(QPlatformIntegration::StyleHint hint) co case QPlatformIntegration::FontSmoothingGamma: return QVariant(QWindowsFontDatabase::fontSmoothingGamma()); case QPlatformIntegration::MouseDoubleClickInterval: - if (const int ms = GetDoubleClickTime()) - return QVariant(ms); + if (const UINT ms = GetDoubleClickTime()) + return QVariant(int(ms)); break; case QPlatformIntegration::UseRtlExtensions: return QVariant(d->m_context.useRTLExtensions()); diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index b7e7867404..5790341dbf 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -541,7 +541,7 @@ Q_STATIC_ASSERT((NumMods == KeyboardLayoutItem::NumQtKeys)); /** Remap return or action key to select key for windows mobile. */ -inline int winceKeyBend(int keyCode) +inline quint32 winceKeyBend(quint32 keyCode) { return KeyTbl[keyCode]; } @@ -575,10 +575,10 @@ QT_END_INCLUDE_NAMESPACE #endif // Q_OS_WINCE // Translate a VK into a Qt key code, or unicode character -static inline int toKeyOrUnicode(int vk, int scancode, unsigned char *kbdBuffer, bool *isDeadkey = 0) +static inline quint32 toKeyOrUnicode(quint32 vk, quint32 scancode, unsigned char *kbdBuffer, bool *isDeadkey = 0) { Q_ASSERT(vk > 0 && vk < 256); - int code = 0; + quint32 code = 0; QChar unicodeBuffer[5]; int res = ToUnicode(vk, scancode, kbdBuffer, reinterpret_cast(unicodeBuffer), 5, 0); // When Ctrl modifier is used ToUnicode does not return correct values. In order to assign the @@ -632,13 +632,13 @@ void QWindowsKeyMapper::changeKeyboard() /* MAKELCID()'s first argument is a WORD, and GetKeyboardLayout() * returns a DWORD. */ - LCID newLCID = MAKELCID((quintptr)GetKeyboardLayout(0), SORT_DEFAULT); + LCID newLCID = MAKELCID(quintptr(GetKeyboardLayout(0)), SORT_DEFAULT); // keyboardInputLocale = qt_localeFromLCID(newLCID); bool bidi = false; wchar_t LCIDFontSig[16]; if (GetLocaleInfo(newLCID, LOCALE_FONTSIGNATURE, LCIDFontSig, sizeof(LCIDFontSig) / sizeof(wchar_t)) - && (LCIDFontSig[7] & (wchar_t)0x0800)) + && (LCIDFontSig[7] & wchar_t(0x0800))) bidi = true; keyboardInputDirection = bidi ? Qt::RightToLeft : Qt::LeftToRight; @@ -662,7 +662,7 @@ void QWindowsKeyMapper::updateKeyMap(const MSG &msg) unsigned char kbdBuffer[256]; // Will hold the complete keyboard state GetKeyboardState(kbdBuffer); const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask; - updatePossibleKeyCodes(kbdBuffer, scancode, msg.wParam); + updatePossibleKeyCodes(kbdBuffer, scancode, quint32(msg.wParam)); } // Fills keyLayout for that vk_key. Values are all characters one can type using that key @@ -721,7 +721,7 @@ void QWindowsKeyMapper::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 keyLayout[vk_key].qtKey[7] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); keyLayout[vk_key].deadkeys |= isDeadKey ? 0x80 : 0; // Add a fall back key for layouts which don't do composition and show non-latin1 characters - int fallbackKey = winceKeyBend(vk_key); + quint32 fallbackKey = winceKeyBend(vk_key); if (!fallbackKey || fallbackKey == Qt::Key_unknown) { fallbackKey = 0; if (vk_key != keyLayout[vk_key].qtKey[0] && vk_key < 0x5B && vk_key > 0x2F) @@ -762,7 +762,7 @@ void QWindowsKeyMapper::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 static inline QString messageKeyText(const MSG &msg) { - const QChar ch = QChar((ushort)msg.wParam); + const QChar ch = QChar(ushort(msg.wParam)); return ch.isNull() ? QString() : QString(ch); } @@ -807,7 +807,7 @@ static void showSystemMenu(QWindow* w) topLevelHwnd, 0); if (ret) - qWindowsWndProc(topLevelHwnd, WM_SYSCOMMAND, ret, 0); + qWindowsWndProc(topLevelHwnd, WM_SYSCOMMAND, WPARAM(ret), 0); } static inline void sendExtendedPressRelease(QWindow *w, int k, @@ -871,7 +871,7 @@ bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, con if (cmd < 0 || cmd > 52) return false; - const int qtKey = CmdTbl[cmd]; + const int qtKey = int(CmdTbl[cmd]); sendExtendedPressRelease(receiver, qtKey, Qt::KeyboardModifier(state), 0, 0, 0); // QTBUG-43343: Make sure to return false if Qt does not handle the key, otherwise, // the keys are not passed to the active media player. @@ -885,10 +885,10 @@ bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, con bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &msg, bool /* grab */) { - const int msgType = msg.message; + const UINT msgType = msg.message; const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask; - quint32 vk_key = msg.wParam; + quint32 vk_key = quint32(msg.wParam); quint32 nModifiers = 0; QWindow *receiver = m_keyGrabber ? m_keyGrabber : window; @@ -949,13 +949,13 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms if (dirStatus == VK_LSHIFT && ((msg.wParam == VK_SHIFT && GetKeyState(VK_LCONTROL)) || (msg.wParam == VK_CONTROL && GetKeyState(VK_LSHIFT)))) { - sendExtendedPressRelease(receiver, Qt::Key_Direction_L, 0, scancode, msg.wParam, nModifiers, QString(), false); + sendExtendedPressRelease(receiver, Qt::Key_Direction_L, 0, scancode, vk_key, nModifiers, QString(), false); result = true; dirStatus = 0; } else if (dirStatus == VK_RSHIFT && ( (msg.wParam == VK_SHIFT && GetKeyState(VK_RCONTROL)) || (msg.wParam == VK_CONTROL && GetKeyState(VK_RSHIFT)))) { - sendExtendedPressRelease(receiver, Qt::Key_Direction_R, 0, scancode, msg.wParam, nModifiers, QString(), false); + sendExtendedPressRelease(receiver, Qt::Key_Direction_R, 0, scancode, vk_key, nModifiers, QString(), false); result = true; dirStatus = 0; } else { @@ -1030,7 +1030,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms || (msg.wParam >= VK_OEM_PLUS && msg.wParam <= VK_OEM_3)) ? 0 : int(Qt::KeypadModifier); default: - if ((uint)msg.lParam == 0x004c0001 || (uint)msg.lParam == 0xc04c0001) + if (uint(msg.lParam) == 0x004c0001 || uint(msg.lParam) == 0xc04c0001) state |= Qt::KeypadModifier; break; } @@ -1042,6 +1042,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms case Qt::Key_Slash: case Qt::Key_NumLock: state |= Qt::KeypadModifier; + break; default: break; } @@ -1051,13 +1052,13 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms if (msgType == WM_KEYDOWN || msgType == WM_IME_KEYDOWN || msgType == WM_SYSKEYDOWN) { // Get the last record of this key press, so we can validate the current state // The record is not removed from the list - KeyRecord *rec = key_recorder.findKey(msg.wParam, false); + KeyRecord *rec = key_recorder.findKey(int(msg.wParam), false); // If rec's state doesn't match the current state, something has changed behind our back // (Consumed by modal widget is one possibility) So, remove the record from the list // This will stop the auto-repeat of the key, should a modifier change, for example if (rec && rec->state != state) { - key_recorder.findKey(msg.wParam, true); + key_recorder.findKey(int(msg.wParam), true); rec = 0; } @@ -1070,11 +1071,11 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms QChar uch; if (PeekMessage(&wm_char, 0, charType, charType, PM_REMOVE)) { // Found a ?_CHAR - uch = QChar((ushort)wm_char.wParam); + uch = QChar(ushort(wm_char.wParam)); if (msgType == WM_SYSKEYDOWN && uch.isLetter() && (msg.lParam & KF_ALTDOWN)) uch = uch.toLower(); // (See doc of WM_SYSCHAR) Alt-letter if (!code && !uch.row()) - code = asciiToKeycode(uch.cell(), state); + code = asciiToKeycode(char(uch.cell()), state); } // Special handling for the WM_IME_KEYDOWN message. Microsoft IME (Korean) will not @@ -1085,7 +1086,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms const QWindowsInputContext *windowsInputContext = qobject_cast(QWindowsIntegration::instance()->inputContext()); if (!(windowsInputContext && windowsInputContext->isComposing())) - vk_key = ImmGetVirtualKey((HWND)window->winId()); + vk_key = ImmGetVirtualKey(reinterpret_cast(window->winId())); BYTE keyState[256]; wchar_t newKey[3] = {0}; GetKeyboardState(keyState); @@ -1105,14 +1106,14 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms uch = QChar(QLatin1Char(0x7f)); // Windows doesn't know this one. } else { if (msgType != WM_SYSKEYDOWN || !code) { - UINT map = MapVirtualKey(msg.wParam, 2); + UINT map = MapVirtualKey(UINT(msg.wParam), 2); // If the high bit of the return value is set, it's a deadkey if (!(map & 0x80000000)) - uch = QChar((ushort)map); + uch = QChar(ushort(map)); } } if (!code && !uch.row()) - code = asciiToKeycode(uch.cell(), state); + code = asciiToKeycode(char(uch.cell()), state); } // Special handling of global Windows hotkeys @@ -1141,9 +1142,9 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms if (rec) { if (code < Qt::Key_Shift || code > Qt::Key_ScrollLock) { QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyRelease, code, - Qt::KeyboardModifier(state), scancode, msg.wParam, nModifiers, rec->text, true); + Qt::KeyboardModifier(state), scancode, quint32(msg.wParam), nModifiers, rec->text, true); QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyPress, code, - Qt::KeyboardModifier(state), scancode, msg.wParam, nModifiers, rec->text, true); + Qt::KeyboardModifier(state), scancode, quint32(msg.wParam), nModifiers, rec->text, true); result = true; } } @@ -1151,7 +1152,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms // and store the key data into our records. else { const QString text = uch.isNull() ? QString() : QString(uch); - const char a = uch.row() ? 0 : uch.cell(); + const char a = uch.row() ? char(0) : char(uch.cell()); const Qt::KeyboardModifiers modifiers(state); #ifndef QT_NO_SHORTCUT // Is Qt interested in the context menu key? @@ -1160,9 +1161,9 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms return false; } #endif // !QT_NO_SHORTCUT - key_recorder.storeKey(msg.wParam, a, state, text); + key_recorder.storeKey(int(msg.wParam), a, state, text); QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyPress, code, - modifiers, scancode, msg.wParam, nModifiers, text, false); + modifiers, scancode, quint32(msg.wParam), nModifiers, text, false); result =true; bool store = true; #ifndef Q_OS_WINCE @@ -1181,7 +1182,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms } #endif // !Q_OS_WINCE if (!store) - key_recorder.findKey(msg.wParam, true); + key_recorder.findKey(int(msg.wParam), true); } } @@ -1191,7 +1192,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms // The key may not be in our records if, for example, the down event was handled by // win32 natively, or our window gets focus while a key is already press, but now gets // the key release event. - KeyRecord* rec = key_recorder.findKey(msg.wParam, true); + const KeyRecord *rec = key_recorder.findKey(int(msg.wParam), true); if (!rec && !(code == Qt::Key_Shift || code == Qt::Key_Control || code == Qt::Key_Meta @@ -1199,13 +1200,14 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms // Someone ate the key down event } else { if (!code) - code = asciiToKeycode(rec->ascii ? rec->ascii : msg.wParam, state); + code = asciiToKeycode(rec->ascii ? char(rec->ascii) : char(msg.wParam), state); // Map SHIFT + Tab to SHIFT + BackTab, QShortcutMap knows about this translation if (code == Qt::Key_Tab && (state & Qt::ShiftModifier) == Qt::ShiftModifier) code = Qt::Key_Backtab; QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyRelease, code, - Qt::KeyboardModifier(state), scancode, msg.wParam, nModifiers, + Qt::KeyboardModifier(state), scancode, quint32(msg.wParam), + nModifiers, (rec ? rec->text : QString()), false); result = true; #ifndef Q_OS_WINCE diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index a8264b55c0..de18426484 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -150,7 +150,7 @@ static bool qt_write_dibv5(QDataStream &s, QImage image) bi.bV5Planes = 1; bi.bV5BitCount = 32; bi.bV5Compression = BI_BITFIELDS; - bi.bV5SizeImage = bpl_bmp*image.height(); + bi.bV5SizeImage = DWORD(bpl_bmp * image.height()); bi.bV5XPelsPerMeter = 0; bi.bV5YPelsPerMeter = 0; bi.bV5ClrUsed = 0; @@ -170,30 +170,29 @@ static bool qt_write_dibv5(QDataStream &s, QImage image) image = image.convertToFormat(QImage::Format_ARGB32); uchar *buf = new uchar[bpl_bmp]; - uchar *b; - memset(buf, 0, bpl_bmp); + memset(buf, 0, size_t(bpl_bmp)); for (int y=image.height()-1; y>=0; y--) { // write the image bits const QRgb *p = reinterpret_cast(image.constScanLine(y)); const QRgb *end = p + image.width(); - b = buf; + uchar *b = buf; while (p < end) { int alpha = qAlpha(*p); if (alpha) { - *b++ = qBlue(*p); - *b++ = qGreen(*p); - *b++ = qRed(*p); + *b++ = uchar(qBlue(*p)); + *b++ = uchar(qGreen(*p)); + *b++ = uchar(qRed(*p)); } else { //white for fully transparent pixels. *b++ = 0xff; *b++ = 0xff; *b++ = 0xff; } - *b++ = alpha; + *b++ = uchar(alpha); p++; } - d->write((char*)buf, bpl_bmp); + d->write(reinterpret_cast(buf), bpl_bmp); if (s.status() != QDataStream::Ok) { delete[] buf; return false; @@ -221,25 +220,22 @@ static bool qt_read_dibv5(QDataStream &s, QImage &image) if (d->atEnd()) return false; - d->read((char *)&bi, sizeof(bi)); // read BITMAPV5HEADER header + d->read(reinterpret_cast(&bi), sizeof(bi)); // read BITMAPV5HEADER header if (s.status() != QDataStream::Ok) return false; - int nbits = bi.bV5BitCount; - int comp = bi.bV5Compression; - if (nbits != 32 || bi.bV5Planes != 1 || comp != BMP_BITFIELDS) + const int nbits = bi.bV5BitCount; + if (nbits != 32 || bi.bV5Planes != 1 || bi.bV5Compression != BMP_BITFIELDS) return false; //Unsupported DIBV5 format - int w = bi.bV5Width, h = bi.bV5Height; - int red_mask = bi.bV5RedMask; - int green_mask = bi.bV5GreenMask; - int blue_mask = bi.bV5BlueMask; - int alpha_mask = bi.bV5AlphaMask; - int red_shift = 0; - int green_shift = 0; - int blue_shift = 0; - int alpha_shift = 0; - QImage::Format format = QImage::Format_ARGB32; + const int w = bi.bV5Width; + int h = bi.bV5Height; + const int red_mask = int(bi.bV5RedMask); + const int green_mask = int(bi.bV5GreenMask); + const int blue_mask = int(bi.bV5BlueMask); + const int alpha_mask = int(bi.bV5AlphaMask); + + const QImage::Format format = QImage::Format_ARGB32; if (bi.bV5Height < 0) h = -h; // support images with negative height @@ -251,30 +247,25 @@ static bool qt_read_dibv5(QDataStream &s, QImage &image) image.setDotsPerMeterX(bi.bV5XPelsPerMeter); image.setDotsPerMeterY(bi.bV5YPelsPerMeter); - red_shift = calc_shift(red_mask); - green_shift = calc_shift(green_mask); - blue_shift = calc_shift(blue_mask); - if (alpha_mask) { - alpha_shift = calc_shift(alpha_mask); - } + const int red_shift = calc_shift(red_mask); + const int green_shift = calc_shift(green_mask); + const int blue_shift = calc_shift(blue_mask); + const int alpha_shift = alpha_mask ? calc_shift(alpha_mask) : 0u; - int bpl = image.bytesPerLine(); + const int bpl = image.bytesPerLine(); uchar *data = image.bits(); - QRgb *p; - QRgb *end; + uchar *buf24 = new uchar[bpl]; - int bpl24 = ((w*nbits+31)/32)*4; - uchar *b; - unsigned int c; + const int bpl24 = ((w * nbits + 31) / 32) * 4; while (--h >= 0) { - p = (QRgb *)(data + h*bpl); - end = p + w; - if (d->read((char *)buf24,bpl24) != bpl24) + QRgb *p = reinterpret_cast(data + h * bpl); + QRgb *end = p + w; + if (d->read(reinterpret_cast(buf24), bpl24) != bpl24) break; - b = buf24; + const uchar *b = buf24; while (p < end) { - c = *b | (*(b+1))<<8 | (*(b+2))<<16 | (*(b+3))<<24; + const int c = *b | (*(b + 1)) << 8 | (*(b + 2)) << 16 | (*(b + 3)) << 24; *p++ = qRgba(((c & red_mask) >> red_shift) , ((c & green_mask) >> green_shift), ((c & blue_mask) >> blue_shift), @@ -289,9 +280,9 @@ static bool qt_read_dibv5(QDataStream &s, QImage &image) uchar *buf = new uchar[bpl]; h = -bi.bV5Height; for (int y = 0; y < h/2; ++y) { - memcpy(buf, data + y*bpl, bpl); - memcpy(data + y*bpl, data + (h-y-1)*bpl, bpl); - memcpy(data + (h-y-1)*bpl, buf, bpl); + memcpy(buf, data + y * bpl, size_t(bpl)); + memcpy(data + y*bpl, data + (h - y -1) * bpl, size_t(bpl)); + memcpy(data + (h - y -1 ) * bpl, buf, size_t(bpl)); } delete [] buf; } @@ -309,7 +300,7 @@ static int getCf(const FORMATETC &formatetc) static FORMATETC setCf(int cf) { FORMATETC formatetc; - formatetc.cfFormat = cf; + formatetc.cfFormat = CLIPFORMAT(cf); formatetc.dwAspect = DVASPECT_CONTENT; formatetc.lindex = -1; formatetc.ptd = NULL; @@ -319,12 +310,12 @@ static FORMATETC setCf(int cf) static bool setData(const QByteArray &data, STGMEDIUM *pmedium) { - HGLOBAL hData = GlobalAlloc(0, data.size()); + HGLOBAL hData = GlobalAlloc(0, SIZE_T(data.size())); if (!hData) return false; void *out = GlobalLock(hData); - memcpy(out, data.data(), data.size()); + memcpy(out, data.data(), size_t(data.size())); GlobalUnlock(hData); pmedium->tymed = TYMED_HGLOBAL; pmedium->hGlobal = hData; @@ -339,8 +330,8 @@ static QByteArray getData(int cf, IDataObject *pDataObj, int lindex = -1) formatetc.lindex = lindex; STGMEDIUM s; if (pDataObj->GetData(&formatetc, &s) == S_OK) { - DWORD * val = (DWORD*)GlobalLock(s.hGlobal); - data = QByteArray::fromRawData((char*)val, GlobalSize(s.hGlobal)); + const void *val = GlobalLock(s.hGlobal); + data = QByteArray::fromRawData(reinterpret_cast(val), int(GlobalSize(s.hGlobal))); data.detach(); GlobalUnlock(s.hGlobal); ReleaseStgMedium(&s); @@ -356,7 +347,7 @@ static QByteArray getData(int cf, IDataObject *pDataObj, int lindex = -1) while(SUCCEEDED(hr)){ hr = s.pstm->Read(szBuffer, sizeof(szBuffer), &actualRead); if (SUCCEEDED(hr) && actualRead > 0) { - data += QByteArray::fromRawData(szBuffer, actualRead); + data += QByteArray::fromRawData(szBuffer, int(actualRead)); } if (actualRead != sizeof(szBuffer)) break; @@ -508,11 +499,11 @@ QWindowsMime::~QWindowsMime() */ int QWindowsMime::registerMimeType(const QString &mime) { - int f = RegisterClipboardFormat(reinterpret_cast (mime.utf16())); + const UINT f = RegisterClipboardFormat(reinterpret_cast (mime.utf16())); if (!f) qErrnoWarning("QWindowsMime::registerMimeType: Failed to register clipboard format"); - return f; + return int(f); } /*! @@ -655,9 +646,9 @@ bool QWindowsMimeText::convertFromMime(const FORMATETC &formatetc, const QMimeDa ++u; } res.truncate(ri); - const int byteLength = res.length() * sizeof(ushort); + const int byteLength = res.length() * int(sizeof(ushort)); QByteArray r(byteLength + 2, '\0'); - memcpy(r.data(), res.unicode(), byteLength); + memcpy(r.data(), res.unicode(), size_t(byteLength)); r[byteLength] = 0; r[byteLength+1] = 0; return setData(r, pmedium); @@ -700,17 +691,17 @@ QVariant QWindowsMimeText::convertToMime(const QString &mime, LPDATAOBJECT pData QString str; QByteArray data = getData(CF_UNICODETEXT, pDataObj); if (!data.isEmpty()) { - str = QString::fromWCharArray((const wchar_t *)data.data()); + str = QString::fromWCharArray(reinterpret_cast(data.constData())); str.replace(QStringLiteral("\r\n"), QStringLiteral("\n")); } else { data = getData(CF_TEXT, pDataObj); if (!data.isEmpty()) { const char* d = data.data(); - const int s = qstrlen(d); + const unsigned s = qstrlen(d); QByteArray r(data.size()+1, '\0'); char* o = r.data(); int j=0; - for (int i=0; i(result.data()); d->pFiles = sizeof(DROPFILES); GetCursorPos(&d->pt); // try d->fNC = true; - char* files = ((char*)d) + d->pFiles; + char *files = (reinterpret_cast(d)) + d->pFiles; d->fWide = true; - wchar_t* f = (wchar_t*)files; + wchar_t *f = reinterpret_cast(files); for (int i=0; i(url.utf16()), + url.length() * int(sizeof(ushort))); } result.append('\0'); result.append('\0'); @@ -854,9 +846,9 @@ QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pD if (data.isEmpty()) return QVariant(); - LPDROPFILES hdrop = (LPDROPFILES)data.data(); + const DROPFILES *hdrop = reinterpret_cast(data.constData()); if (hdrop->fWide) { - const wchar_t* filesw = (const wchar_t *)(data.data() + hdrop->pFiles); + const wchar_t *filesw = reinterpret_cast(data.constData() + hdrop->pFiles); int i = 0; while (filesw[i]) { QString fileurl = QString::fromWCharArray(filesw + i); @@ -864,7 +856,7 @@ QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pD i += fileurl.length()+1; } } else { - const char* files = (const char *)data.data() + hdrop->pFiles; + const char* files = reinterpret_cast(data.constData() + hdrop->pFiles); int i=0; while (files[i]) { urls += QUrl::fromLocalFile(QString::fromLocal8Bit(files+i)); @@ -880,7 +872,7 @@ QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pD QByteArray data = getData(CF_INETURL_W, pDataObj); if (data.isEmpty()) return QVariant(); - return QUrl(QString::fromWCharArray((const wchar_t *)data.constData())); + return QUrl(QString::fromWCharArray(reinterpret_cast(data.constData()))); } else if (canGetData(CF_INETURL, pDataObj)) { QByteArray data = getData(CF_INETURL, pDataObj); if (data.isEmpty()) @@ -1008,14 +1000,14 @@ bool QWindowsMimeHtml::convertFromMime(const FORMATETC &formatetc, const QMimeDa result += ""; // set the correct number for EndHTML - QByteArray pos = QString::number(result.size()).toLatin1(); - memcpy((char *)(result.data() + 53 - pos.length()), pos.constData(), pos.length()); + QByteArray pos = QByteArray::number(result.size()); + memcpy(reinterpret_cast(result.data() + 53 - pos.length()), pos.constData(), size_t(pos.length())); // set correct numbers for StartFragment and EndFragment - pos = QString::number(result.indexOf("") + 20).toLatin1(); - memcpy((char *)(result.data() + 79 - pos.length()), pos.constData(), pos.length()); - pos = QString::number(result.indexOf("")).toLatin1(); - memcpy((char *)(result.data() + 103 - pos.length()), pos.constData(), pos.length()); + pos = QByteArray::number(result.indexOf("") + 20); + memcpy(reinterpret_cast(result.data() + 79 - pos.length()), pos.constData(), size_t(pos.length())); + pos = QByteArray::number(result.indexOf("")); + memcpy(reinterpret_cast(result.data() + 103 - pos.length()), pos.constData(), size_t(pos.length())); return setData(result, pmedium); } @@ -1243,9 +1235,9 @@ bool QBuiltInMimes::convertFromMime(const FORMATETC &formatetc, const QMimeData ++u; } res.truncate(ri); - const int byteLength = res.length() * sizeof(ushort); + const int byteLength = res.length() * int(sizeof(ushort)); QByteArray r(byteLength + 2, '\0'); - memcpy(r.data(), res.unicode(), byteLength); + memcpy(r.data(), res.unicode(), size_t(byteLength)); r[byteLength] = 0; r[byteLength+1] = 0; data = r; @@ -1282,7 +1274,7 @@ QVariant QBuiltInMimes::convertToMime(const QString &mimeType, IDataObject *pDat qCDebug(lcQpaMime) << __FUNCTION__; if (mimeType == QLatin1String("text/html") && preferredType == QVariant::String) { // text/html is in wide chars on windows (compatible with Mozilla) - val = QString::fromWCharArray((const wchar_t *)data.data()); + val = QString::fromWCharArray(reinterpret_cast(data.constData())); } else { val = data; // it should be enough to return the data and let QMimeData do the rest. } @@ -1422,8 +1414,8 @@ bool QLastResortMimes::canConvertToMime(const QString &mimeType, IDataObject *pD if (isCustomMimeType(mimeType)) { // MSDN documentation for QueryGetData says only -1 is supported, so ignore lindex here. QString clipFormat = customMimeType(mimeType); - int cf = RegisterClipboardFormat(reinterpret_cast (clipFormat.utf16())); - return canGetData(cf, pDataObj); + const UINT cf = RegisterClipboardFormat(reinterpret_cast (clipFormat.utf16())); + return canGetData(int(cf), pDataObj); } else if (formats.keys(mimeType).isEmpty()) { // if it is not in there then register it and see if we can get it int cf = QWindowsMime::registerMimeType(mimeType); @@ -1443,8 +1435,8 @@ QVariant QLastResortMimes::convertToMime(const QString &mimeType, IDataObject *p if (isCustomMimeType(mimeType)) { int lindex; QString clipFormat = customMimeType(mimeType, &lindex); - int cf = RegisterClipboardFormat(reinterpret_cast (clipFormat.utf16())); - data = getData(cf, pDataObj, lindex); + const UINT cf = RegisterClipboardFormat(reinterpret_cast (clipFormat.utf16())); + data = getData(int(cf), pDataObj, lindex); } else if (formats.keys(mimeType).isEmpty()) { int cf = QWindowsMime::registerMimeType(mimeType); data = getData(cf, pDataObj); @@ -1593,7 +1585,7 @@ void QWindowsMimeConverter::ensureInitialized() const QString QWindowsMimeConverter::clipboardFormatName(int cf) { wchar_t buf[256] = {0}; - return GetClipboardFormatName(cf, buf, 255) + return GetClipboardFormatName(UINT(cf), buf, 255) ? QString::fromWCharArray(buf) : QString(); } diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index e26010b5c4..32f8285954 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -203,7 +203,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, // Check for events synthesized from touch. Lower 7 bits are touch/pen index, bit 8 indicates touch. // However, when tablet support is active, extraInfo is a packet serial number. This is not a problem // since we do not want to ignore mouse events coming from a tablet. - const quint64 extraInfo = GetMessageExtraInfo(); + const quint64 extraInfo = quint64(GetMessageExtraInfo()); if ((extraInfo & signatureMask) == miWpSignature) { if (extraInfo & 0x80) { // Bit 7 indicates touch event, else tablet pen. source = Qt::MouseEventSynthesizedBySystem; @@ -243,7 +243,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, } QWindowsWindow *platformWindow = static_cast(window->handle()); - const Qt::MouseButtons buttons = keyStateToMouseButtons((int)msg.wParam); + const Qt::MouseButtons buttons = keyStateToMouseButtons(int(msg.wParam)); // If the window was recently resized via mouse doubleclick on the frame or title bar, // we don't get WM_LBUTTONDOWN or WM_LBUTTONDBLCLK for the second click, @@ -418,13 +418,13 @@ static void redirectWheelEvent(QWindow *window, const QPoint &globalPos, int del bool QWindowsMouseHandler::translateMouseWheelEvent(QWindow *window, HWND, MSG msg, LRESULT *) { - const Qt::KeyboardModifiers mods = keyStateToModifiers((int)msg.wParam); + const Qt::KeyboardModifiers mods = keyStateToModifiers(int(msg.wParam)); int delta; if (msg.message == WM_MOUSEWHEEL || msg.message == WM_MOUSEHWHEEL) - delta = (short) HIWORD (msg.wParam); + delta = HIWORD (msg.wParam); else - delta = (int) msg.wParam; + delta = int(msg.wParam); Qt::Orientation orientation = (msg.message == WM_MOUSEHWHEEL || (mods & Qt::AltModifier)) ? @@ -495,15 +495,17 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, return true; const QRect screenGeometry = screen->geometry(); - const int winTouchPointCount = msg.wParam; + const int winTouchPointCount = int(msg.wParam); QScopedArrayPointer winTouchInputs(new TOUCHINPUT[winTouchPointCount]); - memset(winTouchInputs.data(), 0, sizeof(TOUCHINPUT) * winTouchPointCount); + memset(winTouchInputs.data(), 0, sizeof(TOUCHINPUT) * size_t(winTouchPointCount)); QTouchPointList touchPoints; touchPoints.reserve(winTouchPointCount); Qt::TouchPointStates allStates = 0; - QWindowsContext::user32dll.getTouchInputInfo((HANDLE) msg.lParam, msg.wParam, winTouchInputs.data(), sizeof(TOUCHINPUT)); + QWindowsContext::user32dll.getTouchInputInfo(reinterpret_cast(msg.lParam), + UINT(msg.wParam), + winTouchInputs.data(), sizeof(TOUCHINPUT)); for (int i = 0; i < winTouchPointCount; ++i) { const TOUCHINPUT &winTouchInput = winTouchInputs[i]; int id = m_touchInputIDToTouchPointID.value(winTouchInput.dwID, -1); @@ -544,7 +546,7 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, touchPoints.append(touchPoint); } - QWindowsContext::user32dll.closeTouchInputHandle((HANDLE) msg.lParam); + QWindowsContext::user32dll.closeTouchInputHandle(reinterpret_cast(msg.lParam)); // all touch points released, forget the ids we've seen, they may not be reused if (allStates == Qt::TouchPointReleased) diff --git a/src/plugins/platforms/windows/qwindowsnativeimage.cpp b/src/plugins/platforms/windows/qwindowsnativeimage.cpp index 66e64e64b4..3cdfc9f56e 100644 --- a/src/plugins/platforms/windows/qwindowsnativeimage.cpp +++ b/src/plugins/platforms/windows/qwindowsnativeimage.cpp @@ -93,13 +93,13 @@ static inline HBITMAP createDIB(HDC hdc, int width, int height, bmi.blueMask = 0; } - void *bits = 0; + uchar *bits = Q_NULLPTR; HBITMAP bitmap = CreateDIBSection(hdc, reinterpret_cast(&bmi), - DIB_RGB_COLORS, &bits, 0, 0); + DIB_RGB_COLORS, reinterpret_cast(&bits), 0, 0); if (!bitmap || !bits) qFatal("%s: CreateDIBSection failed.", __FUNCTION__); - *bitsIn = (uchar*)bits; + *bitsIn = bits; return bitmap; } @@ -112,7 +112,7 @@ QWindowsNativeImage::QWindowsNativeImage(int width, int height, if (width != 0 && height != 0) { uchar *bits; m_bitmap = createDIB(m_hdc, width, height, format, &bits); - m_null_bitmap = (HBITMAP)SelectObject(m_hdc, m_bitmap); + m_null_bitmap = static_cast(SelectObject(m_hdc, m_bitmap)); m_image = QImage(bits, width, height, format); Q_ASSERT(m_image.paintEngine()->type() == QPaintEngine::Raster); static_cast(m_image.paintEngine())->setDC(m_hdc); diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp index e480c1ebcf..4521f66edd 100644 --- a/src/plugins/platforms/windows/qwindowsole.cpp +++ b/src/plugins/platforms/windows/qwindowsole.cpp @@ -215,7 +215,7 @@ QWindowsOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppe fmtetcs = mc.allFormatsForMime(data); } else { FORMATETC formatetc; - formatetc.cfFormat = CF_PERFORMEDDROPEFFECT; + formatetc.cfFormat = CLIPFORMAT(CF_PERFORMEDDROPEFFECT); formatetc.dwAspect = DVASPECT_CONTENT; formatetc.lindex = -1; formatetc.ptd = NULL; @@ -269,7 +269,7 @@ QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector &fmtetcs) m_lpfmtetcs.reserve(fmtetcs.count()); for (int idx = 0; idx < fmtetcs.count(); ++idx) { LPFORMATETC destetc = new FORMATETC(); - if (copyFormatEtc(destetc, (LPFORMATETC)&(fmtetcs.at(idx)))) { + if (copyFormatEtc(destetc, &(fmtetcs.at(idx)))) { m_lpfmtetcs.append(destetc); } else { m_isNull = true; @@ -363,14 +363,14 @@ QWindowsOleEnumFmtEtc::Next(ULONG celt, LPFORMATETC rgelt, ULONG FAR* pceltFetch nOffset = m_nIndex + i; if (nOffset < ULONG(m_lpfmtetcs.count())) { - copyFormatEtc((LPFORMATETC)&(rgelt[i]), m_lpfmtetcs.at(nOffset)); + copyFormatEtc(rgelt + i, m_lpfmtetcs.at(int(nOffset))); i++; } else { break; } } - m_nIndex += (WORD)i; + m_nIndex += i; if (pceltFetched != NULL) *pceltFetched = i; @@ -397,7 +397,7 @@ QWindowsOleEnumFmtEtc::Skip(ULONG celt) } } - m_nIndex += (WORD)i; + m_nIndex += i; if (i != celt) return ResultFromScode(S_FALSE); @@ -431,7 +431,7 @@ QWindowsOleEnumFmtEtc::Clone(LPENUMFORMATETC FAR* newEnum) return NOERROR; } -bool QWindowsOleEnumFmtEtc::copyFormatEtc(LPFORMATETC dest, LPFORMATETC src) const +bool QWindowsOleEnumFmtEtc::copyFormatEtc(LPFORMATETC dest, const FORMATETC *src) const { if (dest == NULL || src == NULL) return false; diff --git a/src/plugins/platforms/windows/qwindowsole.h b/src/plugins/platforms/windows/qwindowsole.h index 09f6114e2d..bbafa98a0b 100644 --- a/src/plugins/platforms/windows/qwindowsole.h +++ b/src/plugins/platforms/windows/qwindowsole.h @@ -103,7 +103,7 @@ public: STDMETHOD(Clone)(LPENUMFORMATETC FAR* newEnum); private: - bool copyFormatEtc(LPFORMATETC dest, LPFORMATETC src) const; + bool copyFormatEtc(LPFORMATETC dest, const FORMATETC *src) const; ULONG m_dwRefs; ULONG m_nIndex; diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp index fcbe488f93..438aa8752a 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.cpp +++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp @@ -75,10 +75,10 @@ GpuDescription GpuDescription::detect() const HRESULT hr = direct3D9->GetAdapterIdentifier(0, 0, &adapterIdentifier); direct3D9->Release(); if (SUCCEEDED(hr)) { - result.vendorId = int(adapterIdentifier.VendorId); - result.deviceId = int(adapterIdentifier.DeviceId); - result.revision = int(adapterIdentifier.Revision); - result.subSysId = int(adapterIdentifier.SubSysId); + result.vendorId = adapterIdentifier.VendorId; + result.deviceId = adapterIdentifier.DeviceId; + result.revision = adapterIdentifier.Revision; + result.subSysId = adapterIdentifier.SubSysId; QVector version(4, 0); version[0] = HIWORD(adapterIdentifier.DriverVersion.HighPart); // Product version[1] = LOWORD(adapterIdentifier.DriverVersion.HighPart); // Version @@ -329,10 +329,10 @@ bool QWindowsOpenGLTester::testDesktopGL() WNDCLASS wclass; wclass.cbClsExtra = 0; wclass.cbWndExtra = 0; - wclass.hInstance = (HINSTANCE) GetModuleHandle(0); + wclass.hInstance = static_cast(GetModuleHandle(0)); wclass.hIcon = 0; wclass.hCursor = 0; - wclass.hbrBackground = (HBRUSH) (COLOR_BACKGROUND); + wclass.hbrBackground = HBRUSH(COLOR_BACKGROUND); wclass.lpszMenuName = 0; wclass.lpfnWndProc = DefWindowProc; wclass.lpszClassName = className; @@ -371,8 +371,7 @@ bool QWindowsOpenGLTester::testDesktopGL() typedef const GLubyte * (APIENTRY * GetString_t)(GLenum name); GetString_t GetString = reinterpret_cast(::GetProcAddress(lib, "glGetString")); if (GetString) { - const char *versionStr = (const char *) GetString(GL_VERSION); - if (versionStr) { + if (const char *versionStr = reinterpret_cast(GetString(GL_VERSION))) { const QByteArray version(versionStr); const int majorDot = version.indexOf('.'); if (majorDot != -1) { diff --git a/src/plugins/platforms/windows/qwindowsopengltester.h b/src/plugins/platforms/windows/qwindowsopengltester.h index 0fad3d960e..0f1a78daaa 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.h +++ b/src/plugins/platforms/windows/qwindowsopengltester.h @@ -51,10 +51,10 @@ struct GpuDescription QString toString() const; QVariant toVariant() const; - int vendorId; - int deviceId; - int revision; - int subSysId; + uint vendorId; + uint deviceId; + uint revision; + uint subSysId; QVersionNumber driverVersion; QByteArray driverName; QByteArray description; diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index bfcf96ebe7..5accbe87e1 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -152,7 +152,7 @@ BOOL QT_WIN_CALLBACK monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM static inline WindowsScreenDataList monitorData() { WindowsScreenDataList result; - EnumDisplayMonitors(0, 0, monitorEnumCallback, (LPARAM)&result); + EnumDisplayMonitors(0, 0, monitorEnumCallback, reinterpret_cast(&result)); return result; } @@ -200,7 +200,7 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = QPixmap QWindowsScreen::grabWindow(WId window, int x, int y, int width, int height) const { RECT r; - HWND hwnd = window ? (HWND)window : GetDesktopWindow(); + HWND hwnd = window ? reinterpret_cast(window) : GetDesktopWindow(); GetClientRect(hwnd, &r); if (width < 0) width = r.right - r.left; @@ -434,7 +434,7 @@ QWindowsScreenManager::QWindowsScreenManager() : bool QWindowsScreenManager::handleDisplayChange(WPARAM wParam, LPARAM lParam) { - const int newDepth = (int)wParam; + const int newDepth = int(wParam); const WORD newHorizontalResolution = LOWORD(lParam); const WORD newVerticalResolution = HIWORD(lParam); if (newDepth != m_lastDepth || newHorizontalResolution != m_lastHorizontalResolution diff --git a/src/plugins/platforms/windows/qwindowsservices.cpp b/src/plugins/platforms/windows/qwindowsservices.cpp index cc697ba7e4..ae63ac46ae 100644 --- a/src/plugins/platforms/windows/qwindowsservices.cpp +++ b/src/plugins/platforms/windows/qwindowsservices.cpp @@ -53,7 +53,10 @@ static inline bool shellExecute(const QUrl &url) #ifndef Q_OS_WINCE const QString nativeFilePath = url.isLocalFile() ? QDir::toNativeSeparators(url.toLocalFile()) : url.toString(QUrl::FullyEncoded); - const quintptr result = (quintptr)ShellExecute(0, 0, (wchar_t*)nativeFilePath.utf16(), 0, 0, SW_SHOWNORMAL); + const quintptr result = + reinterpret_cast(ShellExecute(0, 0, + reinterpret_cast(nativeFilePath.utf16()), + 0, 0, SW_SHOWNORMAL)); // ShellExecute returns a value greater than 32 if successful if (result <= 32) { qWarning("ShellExecute '%s' failed (error %s).", qPrintable(url.toString()), qPrintable(QString::number(result))); @@ -91,7 +94,7 @@ static inline QString mailCommand() if (debug) qDebug() << __FUNCTION__ << "keyName=" << keyName; command[0] = 0; - if (!RegOpenKeyExW(HKEY_CLASSES_ROOT, (const wchar_t*)keyName.utf16(), 0, KEY_READ, &handle)) { + if (!RegOpenKeyExW(HKEY_CLASSES_ROOT, reinterpret_cast(keyName.utf16()), 0, KEY_READ, &handle)) { DWORD bufferSize = BufferSize; RegQueryValueEx(handle, L"", 0, 0, reinterpret_cast(command), &bufferSize); RegCloseKey(handle); @@ -134,7 +137,8 @@ static inline bool launchMail(const QUrl &url) STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); - if (!CreateProcess(NULL, (wchar_t*)command.utf16(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { + if (!CreateProcess(NULL, reinterpret_cast(const_cast(command.utf16())), + NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { qErrnoWarning("Unable to launch '%s'", qPrintable(command)); return false; } diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp index b27811df9e..222551a86f 100644 --- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp +++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp @@ -316,7 +316,7 @@ QDebug operator<<(QDebug d, const QWindowsTabletDeviceData &t) } #endif // !QT_NO_DEBUG_STREAM -QWindowsTabletDeviceData QWindowsTabletSupport::tabletInit(const quint64 uniqueId, const UINT cursorType) const +QWindowsTabletDeviceData QWindowsTabletSupport::tabletInit(qint64 uniqueId, UINT cursorType) const { QWindowsTabletDeviceData result; result.uniqueId = uniqueId; diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.h b/src/plugins/platforms/windows/qwindowstabletsupport.h index a6d2771206..6e0d92df53 100644 --- a/src/plugins/platforms/windows/qwindowstabletsupport.h +++ b/src/plugins/platforms/windows/qwindowstabletsupport.h @@ -123,7 +123,7 @@ public: private: unsigned options() const; - QWindowsTabletDeviceData tabletInit(const quint64 uniqueId, const UINT cursorType) const; + QWindowsTabletDeviceData tabletInit(qint64 uniqueId, UINT cursorType) const; static QWindowsWinTab32DLL m_winTab32DLL; const HWND m_window; diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 5bbe923fe7..887a217b06 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -456,7 +456,9 @@ static QPixmap loadIconFromShell32(int resourceId, QSizeF size) HMODULE hmod = QSystemLibrary::load(L"shell32"); #endif if (hmod) { - HICON iconHandle = (HICON)LoadImage(hmod, MAKEINTRESOURCE(resourceId), IMAGE_ICON, size.width(), size.height(), 0); + HICON iconHandle = + static_cast(LoadImage(hmod, MAKEINTRESOURCE(resourceId), + IMAGE_ICON, int(size.width()), int(size.height()), 0)); if (iconHandle) { QPixmap iconpixmap = qt_pixmapFromWinHICON(iconHandle); DestroyIcon(iconHandle); @@ -557,7 +559,7 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) con if (sp == FileLinkIcon || sp == DirLinkIcon || sp == DirLinkOpenIcon) { QPainter painter(&pixmap); QPixmap link = loadIconFromShell32(30, pixmapSize); - painter.drawPixmap(0, 0, pixmapSize.width(), pixmapSize.height(), link); + painter.drawPixmap(0, 0, int(pixmapSize.width()), int(pixmapSize.height()), link); } pixmap.setDevicePixelRatio(scaleFactor); return pixmap; @@ -632,7 +634,8 @@ static QPixmap pixmapFromShellImageList(int iImageList, const SHFILEINFO &info) return result; IImageList *imageList = 0; - HRESULT hr = QWindowsContext::shell32dll.sHGetImageList(iImageList, iID_IImageList, (void **)&imageList); + HRESULT hr = QWindowsContext::shell32dll.sHGetImageList(iImageList, iID_IImageList, + reinterpret_cast(&imageList)); if (hr != S_OK) return result; HICON hIcon; @@ -664,7 +667,7 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s QPixmap pixmap; const QString filePath = QDir::toNativeSeparators(fileInfo.filePath()); - const int width = size.width(); + const int width = int(size.width()); const int iconSize = width > 16 ? SHGFI_LARGEICON : SHGFI_SMALLICON; const int requestedImageListSize = #ifdef USE_IIMAGELIST From 7906255ef2412168dc94768ec7f73ee41b159804 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 11 Feb 2016 13:17:04 +0100 Subject: [PATCH 072/118] doc: Clean up old references to QApplication for GUI application Since Qt 5.0, there's been a separation between QGuiApplication for generic GUI applications, and QApplication for applications using Qt Widgets. The docs in QCoreApplication has not reflected this, however, and was still recommending QApplication for any GUI app. Change-Id: I7b2b166170d1e20755889767cda3d555fbbc666a Reviewed-by: Martin Smith Reviewed-by: Nico Vertriest --- src/corelib/kernel/qcoreapplication.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 48d70f2747..6dcd0ed5b4 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -617,7 +617,8 @@ void QCoreApplicationPrivate::initLocale() This class is used by non-GUI applications to provide their event loop. For non-GUI application that uses Qt, there should be exactly one QCoreApplication object. For GUI applications, see - QApplication. + QGuiApplication. For applications that use the Qt Widgets module, + see QApplication. QCoreApplication contains the main event loop, where all events from the operating system (e.g., timer and network events) and @@ -631,10 +632,10 @@ void QCoreApplicationPrivate::initLocale() operations can call processEvents() to keep the application responsive. - In general, we recommend that you create a QCoreApplication or a - QApplication object in your \c main() function as early as - possible. exec() will not return until the event loop exits; e.g., - when quit() is called. + In general, we recommend that you create a QCoreApplication, + QGuiApplication or a QApplication object in your \c main() + function as early as possible. exec() will not return until + the event loop exits; e.g., when quit() is called. Several static convenience functions are also provided. The QCoreApplication object is available from instance(). Events can @@ -676,8 +677,8 @@ void QCoreApplicationPrivate::initLocale() instance, when converting between data types such as floats and strings, since the notation may differ between locales. To get around this problem, call the POSIX function \c{setlocale(LC_NUMERIC,"C")} - right after initializing QApplication or QCoreApplication to reset - the locale that is used for number formatting to "C"-locale. + right after initializing QApplication, QGuiApplication or QCoreApplication + to reset the locale that is used for number formatting to "C"-locale. \sa QGuiApplication, QAbstractEventDispatcher, QEventLoop, {Semaphores Example}, {Wait Conditions Example} @@ -687,7 +688,7 @@ void QCoreApplicationPrivate::initLocale() \fn static QCoreApplication *QCoreApplication::instance() Returns a pointer to the application's QCoreApplication (or - QApplication) instance. + QGuiApplication/QApplication) instance. If no instance has been allocated, \c null is returned. */ @@ -1868,7 +1869,7 @@ void QCoreApplication::quit() Installing or removing a QTranslator, or changing an installed QTranslator generates a \l{QEvent::LanguageChange}{LanguageChange} event for the - QCoreApplication instance. A QApplication instance will propagate the event + QCoreApplication instance. A QGuiApplication instance will propagate the event to all toplevel windows, where a reimplementation of changeEvent can re-translate the user interface by passing user-visible strings via the tr() function to the respective property setters. User-interface classes From aa85ebc266ea7415a883094ea735f549552ff5ac Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Mon, 15 Feb 2016 15:07:53 +0200 Subject: [PATCH 073/118] Android: Fix immersive mode The activity exits immersive mode when displaying a dialog. To fix the problem we must use onWindowFocusChanged to update updateFullScreen every time when we've gotten the focus. Task-number: QTBUG-38759 Change-Id: I9f11a82dba484dbec6daba7cbf116f16fe2ba372 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../qtproject/qt5/android/QtActivityDelegate.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index ac77de0bab..4cce86e8bb 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -92,6 +92,7 @@ public class QtActivityDelegate private Method m_super_onConfigurationChanged = null; private Method m_super_onActivityResult = null; private Method m_super_dispatchGenericMotionEvent = null; + private Method m_super_onWindowFocusChanged = null; private static final String NATIVE_LIBRARIES_KEY = "native.libraries"; private static final String BUNDLED_LIBRARIES_KEY = "bundled.libraries"; @@ -520,6 +521,7 @@ public class QtActivityDelegate m_super_onKeyUp = m_activity.getClass().getMethod("super_onKeyUp", Integer.TYPE, KeyEvent.class); m_super_onConfigurationChanged = m_activity.getClass().getMethod("super_onConfigurationChanged", Configuration.class); m_super_onActivityResult = m_activity.getClass().getMethod("super_onActivityResult", Integer.TYPE, Integer.TYPE, Intent.class); + m_super_onWindowFocusChanged = m_activity.getClass().getMethod("super_onWindowFocusChanged", Boolean.TYPE); if (Build.VERSION.SDK_INT >= 12) { try { m_super_dispatchGenericMotionEvent = m_activity.getClass().getMethod("super_dispatchGenericMotionEvent", MotionEvent.class); @@ -943,6 +945,16 @@ public class QtActivityDelegate } } + public void onWindowFocusChanged(boolean hasFocus) { + try { + m_super_onWindowFocusChanged.invoke(m_activity, hasFocus); + } catch (Exception e) { + e.printStackTrace(); + } + if (hasFocus) + updateFullScreen(); + } + public void onConfigurationChanged(Configuration configuration) { try { From 7cd23a7d5f5b7b10c0e317afcf8bc49020a42e53 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Thu, 18 Feb 2016 18:12:57 +0300 Subject: [PATCH 074/118] xcb: Properly initialize available geometry when XRandR is missing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Take an intersection of the screen geometry and the work area. Change-Id: Ia61d090ac103cb4d13d656ec09037f642b255a79 Reviewed-by: Błażej Szczygieł Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbscreen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index f3d381b99e..0ef7166b90 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -208,7 +208,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe m_geometry = QRect(QPoint(), m_virtualSize); if (m_availableGeometry.isEmpty()) - m_availableGeometry = m_geometry; + m_availableGeometry = m_geometry & m_virtualDesktop->workArea(); readXResources(); From 3f4eba746d23550be19dc4edafe193fa5ce0d3d4 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 18 Feb 2016 14:05:39 +0100 Subject: [PATCH 075/118] xcb: properly initialize size in millimeters if XRandR is not supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QXcbScreen did not set the m_sizeMillimeters if the xcb connection does not support XRandR. This caused physicalSize() to return an invalid QSize. This change fixes a regression compared to Qt 5.4 discovered by a broken unit test for KWin on KDE's CI system, which uses Xvfb and by that no XRandR support. Task-number: QTBUG-49885 Change-Id: Ie472a194ba410f0748ccfda8aa467727fafa10a3 Reviewed-by: Błażej Szczygieł Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbscreen.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 0ef7166b90..28b1753712 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -210,6 +210,9 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe if (m_availableGeometry.isEmpty()) m_availableGeometry = m_geometry & m_virtualDesktop->workArea(); + if (m_sizeMillimeters.isEmpty()) + m_sizeMillimeters = m_virtualSizeMillimeters; + readXResources(); QScopedPointer rootAttribs( From 13034e67c0fa1a5ae1899dcb62869da42d84626f Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 30 Jun 2015 22:01:17 +0200 Subject: [PATCH 076/118] Make public headers compile with -Wzero-as-null-pointer-constant ... or similar. This amends previous commits that converted the majority of cases. Task-number: QTBUG-45291 Change-Id: I219cdeddca7063a56efeb4fee0e5bb2cbdc7732b Reviewed-by: Lars Knoll Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/arch/qatomic_cxx11.h | 8 ++++---- src/gui/image/qimage.h | 2 +- src/gui/kernel/qevent.h | 2 +- src/gui/opengl/qopenglextrafunctions.h | 2 +- src/gui/painting/qpen.h | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/corelib/arch/qatomic_cxx11.h b/src/corelib/arch/qatomic_cxx11.h index 4136e09ce2..baa3d65faf 100644 --- a/src/corelib/arch/qatomic_cxx11.h +++ b/src/corelib/arch/qatomic_cxx11.h @@ -144,7 +144,7 @@ template struct QAtomicOps static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return false; } template - static bool testAndSetRelaxed(std::atomic &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW + static bool testAndSetRelaxed(std::atomic &_q_value, T expectedValue, T newValue, T *currentValue = Q_NULLPTR) Q_DECL_NOTHROW { bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_relaxed); if (currentValue) @@ -153,7 +153,7 @@ template struct QAtomicOps } template - static bool testAndSetAcquire(std::atomic &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW + static bool testAndSetAcquire(std::atomic &_q_value, T expectedValue, T newValue, T *currentValue = Q_NULLPTR) Q_DECL_NOTHROW { bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acquire); if (currentValue) @@ -162,7 +162,7 @@ template struct QAtomicOps } template - static bool testAndSetRelease(std::atomic &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW + static bool testAndSetRelease(std::atomic &_q_value, T expectedValue, T newValue, T *currentValue = Q_NULLPTR) Q_DECL_NOTHROW { bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_release); if (currentValue) @@ -171,7 +171,7 @@ template struct QAtomicOps } template - static bool testAndSetOrdered(std::atomic &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW + static bool testAndSetOrdered(std::atomic &_q_value, T expectedValue, T newValue, T *currentValue = Q_NULLPTR) Q_DECL_NOTHROW { bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acq_rel); if (currentValue) diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 888c7beb32..d05044c44b 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -138,7 +138,7 @@ public: QImage(const QImage &); #ifdef Q_COMPILER_RVALUE_REFS inline QImage(QImage &&other) Q_DECL_NOEXCEPT - : QPaintDevice(), d(0) + : QPaintDevice(), d(Q_NULLPTR) { qSwap(d, other.d); } #endif ~QImage(); diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index b90fce97e0..ed2deda9a0 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -795,7 +795,7 @@ public: TouchPoint(const TouchPoint &other); #ifdef Q_COMPILER_RVALUE_REFS TouchPoint(TouchPoint &&other) Q_DECL_NOEXCEPT - : d(0) + : d(Q_NULLPTR) { qSwap(d, other.d); } TouchPoint &operator=(TouchPoint &&other) Q_DECL_NOEXCEPT { qSwap(d, other.d); return *this; } diff --git a/src/gui/opengl/qopenglextrafunctions.h b/src/gui/opengl/qopenglextrafunctions.h index 6558284bd0..c53c3efba7 100644 --- a/src/gui/opengl/qopenglextrafunctions.h +++ b/src/gui/opengl/qopenglextrafunctions.h @@ -404,7 +404,7 @@ public: void glVertexBindingDivisor(GLuint bindingindex, GLuint divisor); private: - static bool isInitialized(const QOpenGLExtraFunctionsPrivate *d) { return d != 0; } + static bool isInitialized(const QOpenGLExtraFunctionsPrivate *d) { return d != Q_NULLPTR; } }; class QOpenGLExtraFunctionsPrivate : public QOpenGLFunctionsPrivate diff --git a/src/gui/painting/qpen.h b/src/gui/painting/qpen.h index 6ce50ae1d0..bfa1553c68 100644 --- a/src/gui/painting/qpen.h +++ b/src/gui/painting/qpen.h @@ -65,7 +65,7 @@ public: QPen &operator=(const QPen &pen) Q_DECL_NOTHROW; #ifdef Q_COMPILER_RVALUE_REFS QPen(QPen &&other) Q_DECL_NOTHROW - : d(other.d) { other.d = 0; } + : d(other.d) { other.d = Q_NULLPTR; } QPen &operator=(QPen &&other) Q_DECL_NOTHROW { qSwap(d, other.d); return *this; } #endif From 9868d8af8316c01f28255110c28e11344ea6f7a5 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 18 Feb 2016 14:06:02 +0100 Subject: [PATCH 077/118] xcb: include Fix trouble compiling with gcc 4.4.7 on Centos 6 Change-Id: Id81bd570e896507a07388257c4f75f80b4b468fd Reviewed-by: Friedemann Kleint --- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 969b6deed0..81cdaa56c5 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -38,6 +38,7 @@ #include "qtouchdevice.h" #include #include +#include #ifdef XCB_USE_XINPUT2 From 1c87c3bdc65dfe729801bcfc90c986a70cab2d90 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 5 Feb 2016 14:54:58 +0100 Subject: [PATCH 078/118] remove dead code re CONFIG+=generate_pbxbuild_makefile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit evidently, nothing and nobody sets this option, as it's been completely broken since 6234dec41f (qt 5.5) and apparently nobody noticed. Change-Id: I5a82ebd963a292af4689397875dde096f63d751a Reviewed-by: Tor Arne Vestbø --- qmake/generators/mac/pbuilder_pbx.cpp | 39 --------------------------- 1 file changed, 39 deletions(-) diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index ca7c466006..cf0c4a81a3 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -103,19 +103,6 @@ struct ProjectBuilderSubDirs { bool ProjectBuilderMakefileGenerator::writeSubDirs(QTextStream &t) { - if(project->isActiveConfig("generate_pbxbuild_makefile")) { - QString mkwrap = fileFixify(pbx_dir + Option::dir_sep + ".." + Option::dir_sep + project->first("MAKEFILE"), - FileFixifyToIndir); - QFile mkwrapf(mkwrap); - if(mkwrapf.open(QIODevice::WriteOnly | QIODevice::Text)) { - debug_msg(1, "pbuilder: Creating file: %s", mkwrap.toLatin1().constData()); - QTextStream mkwrapt(&mkwrapf); - writingUnixMakefileGenerator = true; - UnixMakefileGenerator::writeSubDirs(mkwrapt); - writingUnixMakefileGenerator = false; - } - } - //HEADER const int pbVersion = pbuilderVersion(); t << "// !$*UTF8*$!\n" @@ -1666,32 +1653,6 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t" << writeSettings("rootObject", keyFor("QMAKE_PBX_ROOT")) << ";\n" << "}\n"; - if(project->isActiveConfig("generate_pbxbuild_makefile")) { - QString mkwrap = Option::output_dir + project->first("/MAKEFILE"); - QFile mkwrapf(mkwrap); - if(mkwrapf.open(QIODevice::WriteOnly | QIODevice::Text)) { - writingUnixMakefileGenerator = true; - debug_msg(1, "pbuilder: Creating file: %s", mkwrap.toLatin1().constData()); - QTextStream mkwrapt(&mkwrapf); - writeHeader(mkwrapt); - const char cleans[] = "preprocess_clean "; - const QString cmd = escapeFilePath(project->first("QMAKE_ORIG_TARGET") + projectSuffix() + "/") + " && " + pbxbuild(); - mkwrapt << "#This is a makefile wrapper for PROJECT BUILDER\n" - << "all:\n\t" - << "cd " << cmd << "\n" - << "install: all\n\t" - << "cd " << cmd << " install\n" - << "distclean clean: preprocess_clean\n\t" - << "cd " << cmd << " clean\n" - << (!did_preprocess ? cleans : "") << ":\n"; - if(did_preprocess) - mkwrapt << cleans << ":\n\t" - << "make -f " - << pbx_dir << Option::dir_sep << "qt_preprocess.mak $@\n"; - writingUnixMakefileGenerator = false; - } - } - // Scheme { QString xcodeSpecDir = project->first("QMAKE_XCODE_SPECDIR").toQString(); From 5260c01bbe0e59d566786157b6dae705e981bb3e Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 3 Feb 2016 17:00:59 +0100 Subject: [PATCH 079/118] load qt_common in qt_helper_lib this has multiple consequences: - we do sane DESTDIR replacement for debug_and_release builds, fixing QTBUG-47313 - we don't create debug/release subdirectories, fixing QTBUG-47639. this only makes sense given the complementary call of $$qt5LibraryTarget() - we patch up the .prl files upon installation Task-number: QTBUG-47313 Task-number: QTBUG-47639 Change-Id: Id409bbd26781a773409b94835ab6b97e71569322 Reviewed-by: Joerg Bornemann --- mkspecs/features/qt_helper_lib.prf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mkspecs/features/qt_helper_lib.prf b/mkspecs/features/qt_helper_lib.prf index 70a17995cf..ebc629f57f 100644 --- a/mkspecs/features/qt_helper_lib.prf +++ b/mkspecs/features/qt_helper_lib.prf @@ -14,6 +14,9 @@ load(qt_build_paths) TEMPLATE = lib CONFIG -= qt +CONFIG -= warning_clean # Don't presume 3rd party code to be clean +load(qt_common) + contains(QT_CONFIG, debug_and_release): CONFIG += debug_and_release contains(QT_CONFIG, build_all): CONFIG += build_all From a5ec7163f97fe6e04bb921eb98c6da48659fc09a Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 16 Dec 2015 12:47:01 +0100 Subject: [PATCH 080/118] unhack qt_install_headers vs. lib_bundle instead of unsetting the flag later on, don't set it in the first place. Change-Id: Id448500b02b5c3e1dc7c332cc178a84c7fd2cfdc Reviewed-by: Joerg Bornemann --- mkspecs/features/qt_module.prf | 1 - mkspecs/features/qt_module_headers.prf | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf index bb28af975f..aefd3aee1c 100644 --- a/mkspecs/features/qt_module.prf +++ b/mkspecs/features/qt_module.prf @@ -116,7 +116,6 @@ lib_bundle { QMAKE_BUNDLE_EXTENSION = .framework QMAKE_INFO_PLIST = $$QMAKESPEC/Info.plist.lib } - CONFIG -= qt_install_headers #no need to install these as well !debug_and_release|!build_all|CONFIG(release, debug|release) { FRAMEWORK_HEADERS.version = Versions FRAMEWORK_HEADERS.files = $$SYNCQT.HEADER_FILES $$SYNCQT.HEADER_CLASSES diff --git a/mkspecs/features/qt_module_headers.prf b/mkspecs/features/qt_module_headers.prf index eb1db08405..094c854ef0 100644 --- a/mkspecs/features/qt_module_headers.prf +++ b/mkspecs/features/qt_module_headers.prf @@ -99,7 +99,8 @@ git_build: \ else: \ INC_PATH = $$MODULE_BASE_INDIR include($$INC_PATH/include/$$MODULE_INCNAME/headers.pri, "", true) -CONFIG += qt_install_headers +!lib_bundle: \ # Headers are embedded into the bundle, so don't install them separately. + CONFIG += qt_install_headers alien_syncqt: return() From 1ffce57157c7a6ce7fb9d58776ee1dacd2ded61b Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 19 Feb 2016 15:43:37 +0100 Subject: [PATCH 081/118] Windows DirectWrite: Improve error messages for font engine creation. Fix up debug operator for QFontDef, add one for LOGFONT and output both should creation fail. Task-number: QTBUG-51260 Change-Id: I5cbcd392edd811c6b9470ddbb095d41a9185d208 Reviewed-by: Joerg Bornemann --- .../windows/qwindowsfontdatabase.cpp | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index 322ba0ec27..05e5af418a 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -634,11 +634,24 @@ 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; + d.noquote(); + d << "QFontDef(Family=\"" << def.family << '"'; + if (!def.styleName.isEmpty()) + d << ", stylename=" << def.styleName; + d << ", pointsize=" << def.pointSize << ", pixelsize=" << def.pixelSize + << ", styleHint=" << def.styleHint << ", weight=" << def.weight + << ", stretch=" << def.stretch << ", hintingPreference=" + << def.hintingPreference << ')'; + return d; +} + +QDebug operator<<(QDebug d, const LOGFONT &lf) +{ + QDebugStateSaver saver(d); + d.nospace(); + d.noquote(); + d << "LOGFONT(\"" << QString::fromWCharArray(lf.lfFaceName) + << "\", lfWidth=" << lf.lfWidth << ", lfHeight=" << lf.lfHeight << ')'; return d; } #endif // !QT_NO_DEBUG_STREAM @@ -1752,12 +1765,16 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, IDWriteFont *directWriteFont = 0; HRESULT hr = data->directWriteGdiInterop->CreateFontFromLOGFONT(&lf, &directWriteFont); if (FAILED(hr)) { - qErrnoWarning("%s: CreateFontFromLOGFONT failed", __FUNCTION__); + const QString errorString = qt_error_string(int(GetLastError())); + qWarning().noquote().nospace() << "DirectWrite: CreateFontFromLOGFONT() failed (" + << errorString << ") for " << request << ' ' << lf << " dpi=" << dpi; } else { IDWriteFontFace *directWriteFontFace = NULL; hr = directWriteFont->CreateFontFace(&directWriteFontFace); if (FAILED(hr)) { - qErrnoWarning("%s: CreateFontFace failed", __FUNCTION__); + const QString errorString = qt_error_string(int(GetLastError())); + qWarning().noquote() << "DirectWrite: CreateFontFace() failed (" + << errorString << ") for " << request << ' ' << lf << " dpi=" << dpi; } else { QWindowsFontEngineDirectWrite *fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace, request.pixelSize, From b6bc41f9dfe2223f9f3abd9cde848c669d29d152 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 17 Feb 2016 15:06:41 -0800 Subject: [PATCH 082/118] QMenu: Add delegate related notes to OS X-only API Change-Id: I88bb4fdb2c11da0602e4c9f6637bbdeaa715aba0 Reviewed-by: Jake Petroules --- src/widgets/widgets/qmenu_mac.mm | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/widgets/widgets/qmenu_mac.mm b/src/widgets/widgets/qmenu_mac.mm index 5322a8f3f5..184e4d7bb1 100644 --- a/src/widgets/widgets/qmenu_mac.mm +++ b/src/widgets/widgets/qmenu_mac.mm @@ -67,8 +67,11 @@ inline QPlatformNativeInterface::NativeResourceForIntegrationFunction resolvePla \since 5.2 Returns the native NSMenu for this menu. Available on OS X only. + + \note Qt sets the delegate on the native menu. If you need to set your own + delegate, make sure you save the original one and forward any calls to it. */ -NSMenu* QMenu::toNSMenu() +NSMenu *QMenu::toNSMenu() { // Call into the cocoa platform plugin: qMenuToNSMenu(platformMenu()) QPlatformNativeInterface::NativeResourceForIntegrationFunction function = resolvePlatformFunction("qmenutonsmenu"); @@ -133,8 +136,11 @@ void QMenuPrivate::moveWidgetToPlatformItem(QWidget *widget, QPlatformMenuItem* \since 5.2 Returns the native NSMenu for this menu bar. Available on OS X only. + + \note Qt may set the delegate on the native menu bar. If you need to set your + own delegate, make sure you save the original one and forward any calls to it. */ -NSMenu* QMenuBar::toNSMenu() +NSMenu *QMenuBar::toNSMenu() { // Call into the cocoa platform plugin: qMenuBarToNSMenu(platformMenuBar()) QPlatformNativeInterface::NativeResourceForIntegrationFunction function = resolvePlatformFunction("qmenubartonsmenu"); From 41706400f605524a5a9953714aa0cfbf811dba7e Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 17 Feb 2016 16:35:03 -0800 Subject: [PATCH 083/118] QCocoaMenuItem: Use the right Objective C class forwarding macros Change-Id: Icdde469e6854c250d44c88fc79b7615647f0783a Reviewed-by: Jake Petroules --- src/plugins/platforms/cocoa/qcocoamenuitem.h | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.h b/src/plugins/platforms/cocoa/qcocoamenuitem.h index 289f38fd18..1cd15e686c 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.h +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.h @@ -40,17 +40,10 @@ //#define QT_COCOA_ENABLE_MENU_DEBUG -#ifdef __OBJC__ -#define QT_FORWARD_DECLARE_OBJC_CLASS(__KLASS__) @class __KLASS__ -#else -#define QT_FORWARD_DECLARE_OBJC_CLASS(__KLASS__) typedef struct objc_object __KLASS__ -#endif - -QT_FORWARD_DECLARE_OBJC_CLASS(NSMenuItem); -QT_FORWARD_DECLARE_OBJC_CLASS(NSMenu); -QT_FORWARD_DECLARE_OBJC_CLASS(NSObject); -QT_FORWARD_DECLARE_OBJC_CLASS(NSView); - +Q_FORWARD_DECLARE_OBJC_CLASS(NSMenuItem); +Q_FORWARD_DECLARE_OBJC_CLASS(NSMenu); +Q_FORWARD_DECLARE_OBJC_CLASS(NSObject); +Q_FORWARD_DECLARE_OBJC_CLASS(NSView); QT_BEGIN_NAMESPACE From a425b5f19c20f357acf92950dda7b395c1ee4c72 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 18 Feb 2016 20:20:09 +0100 Subject: [PATCH 084/118] QWindowsGLContext: replace homebrew Array with std::vector std::vector is all that the Array original author dreamed about, and more: never shrinks capacity, non CoWed, ... Appart from append(), the Array API was modeled after std::vector (size_t size_type, etc) already, so the port to std::vector is minimal. The only change besides append() -> push_back() was not assuming const_iterator being const T*. Remove now-unused Array. Change-Id: I02bc71441d01e554e320746d82dbc00f74c5466d Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/array.h | 102 ------------------ .../platforms/windows/qwindowsglcontext.cpp | 19 ++-- .../platforms/windows/qwindowsglcontext.h | 5 +- src/plugins/platforms/windows/windows.pri | 1 - 4 files changed, 12 insertions(+), 115 deletions(-) delete mode 100644 src/plugins/platforms/windows/array.h diff --git a/src/plugins/platforms/windows/array.h b/src/plugins/platforms/windows/array.h deleted file mode 100644 index 98d2496a7f..0000000000 --- a/src/plugins/platforms/windows/array.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** 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.LGPL3 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-3.0.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 (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef ARRAY_H -#define ARRAY_H - -#include -#include - -QT_BEGIN_NAMESPACE - -/* A simple, non-shared array. */ - -template -class Array -{ - Q_DISABLE_COPY(Array) -public: - enum { initialSize = 5 }; - - typedef T* const_iterator; - - explicit Array(size_t size= 0) : data(0), m_capacity(0), m_size(0) - { if (size) resize(size); } - ~Array() { delete [] data; } - - T *data; - inline size_t size() const { return m_size; } - inline const_iterator begin() const { return data; } - inline const_iterator end() const { return data + m_size; } - - inline void append(const T &value) - { - const size_t oldSize = m_size; - resize(m_size + 1); - data[oldSize] = value; - } - - inline void resize(size_t size) - { - if (size > m_size) - reserve(size > 1 ? size + size / 2 : size_t(initialSize)); - m_size = size; - } - - void reserve(size_t capacity) - { - if (capacity > m_capacity) { - const T *oldData = data; - data = new T[capacity]; - if (oldData) { - std::copy(oldData, oldData + m_size, data); - delete [] oldData; - } - m_capacity = capacity; - } - } - -private: - size_t m_capacity; - size_t m_size; -}; - -QT_END_NAMESPACE - -#endif // ARRAY_H diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index 71b2387c7c..1adce2a874 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -1270,10 +1270,9 @@ bool QWindowsGLContext::updateObtainedParams(HDC hdc, int *obtainedSwapInterval) void QWindowsGLContext::releaseDCs() { - const QOpenGLContextData *end = m_windowContexts.end(); - for (const QOpenGLContextData *p = m_windowContexts.begin(); p < end; ++p) - ReleaseDC(p->hwnd, p->hdc); - m_windowContexts.resize(0); + for (const auto &e : m_windowContexts) + ReleaseDC(e.hwnd, e.hdc); + m_windowContexts.clear(); } static inline QWindowsWindow *glWindowOf(QPlatformSurface *s) @@ -1288,12 +1287,12 @@ static inline HWND handleOf(QPlatformSurface *s) // Find a window in a context list. static inline const QOpenGLContextData * - findByHWND(const Array &data, HWND hwnd) + findByHWND(const std::vector &data, HWND hwnd) { - const QOpenGLContextData *end = data.end(); - for (const QOpenGLContextData *p = data.begin(); p < end; ++p) - if (p->hwnd == hwnd) - return p; + for (const auto &e : data) { + if (e.hwnd == hwnd) + return &e; + } return 0; } @@ -1347,7 +1346,7 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface) if (m_obtainedFormat.swapBehavior() == QSurfaceFormat::DoubleBuffer) window->setFlag(QWindowsWindow::OpenGLDoubleBuffered); } - m_windowContexts.append(newContext); + m_windowContexts.push_back(newContext); m_lost = false; bool success = QOpenGLStaticContext::opengl32.wglMakeCurrent(newContext.hdc, newContext.renderingContext); diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h index 791a17301e..3acfed1ccf 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.h +++ b/src/plugins/platforms/windows/qwindowsglcontext.h @@ -40,12 +40,13 @@ #ifndef QWINDOWSGLCONTEXT_H #define QWINDOWSGLCONTEXT_H -#include "array.h" #include "qtwindows_additional.h" #include "qwindowsopenglcontext.h" #include +#include + QT_BEGIN_NAMESPACE class QDebug; @@ -264,7 +265,7 @@ private: QOpenGLContext *m_context; QSurfaceFormat m_obtainedFormat; HGLRC m_renderingContext; - Array m_windowContexts; + std::vector m_windowContexts; PIXELFORMATDESCRIPTOR m_obtainedPixelFormatDescriptor; int m_pixelFormat; bool m_extensionsUsed; diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index 67af5c03ef..766168ccb8 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -55,7 +55,6 @@ HEADERS += \ $$PWD/qwindowsmime.h \ $$PWD/qwindowsinternalmimedata.h \ $$PWD/qwindowscursor.h \ - $$PWD/array.h \ $$PWD/qwindowsinputcontext.h \ $$PWD/qwindowstheme.h \ $$PWD/qwindowsdialoghelpers.h \ From 7ce90fe6fabc946335270552eab03486580df1e3 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Thu, 18 Feb 2016 11:40:39 +0300 Subject: [PATCH 085/118] QFileSystemModelPrivate: remove unused code Change-Id: I83df0d0bbac66957dc06e2805acf2c47d172fed8 Reviewed-by: Edward Welbourne Reviewed-by: Marc Mutz --- src/widgets/dialogs/qfilesystemmodel_p.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/widgets/dialogs/qfilesystemmodel_p.h b/src/widgets/dialogs/qfilesystemmodel_p.h index 8e622e777a..af3406b699 100644 --- a/src/widgets/dialogs/qfilesystemmodel_p.h +++ b/src/widgets/dialogs/qfilesystemmodel_p.h @@ -268,16 +268,6 @@ public: delayedSortTimer.start(0); } - static bool caseInsensitiveLessThan(const QString &s1, const QString &s2) - { - return QString::compare(s1, s2, Qt::CaseInsensitive) < 0; - } - - static bool nodeCaseInsensitiveLessThan(const QFileSystemModelPrivate::QFileSystemNode &s1, const QFileSystemModelPrivate::QFileSystemNode &s2) - { - return QString::compare(s1.fileName, s2.fileName, Qt::CaseInsensitive) < 0; - } - QIcon icon(const QModelIndex &index) const; QString name(const QModelIndex &index) const; QString displayName(const QModelIndex &index) const; From 923be3f78ca1b2fc4be8bd4b2ac80b4f1b4df152 Mon Sep 17 00:00:00 2001 From: Andre Somers Date: Fri, 19 Feb 2016 07:36:00 +0100 Subject: [PATCH 086/118] Fix small textual error in documentation for QFlags::setFlag Change-Id: I075932cfb9fdd38fb8d54da19e7d72b8cdec49f3 Reviewed-by: Martin Smith Reviewed-by: Mitch Curtis --- src/corelib/global/qglobal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 3ea121fcc2..cbcc6d02a6 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -430,7 +430,7 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in \since 5.7 Sets the indicated \a flag if \a on is \c true or unsets it if - it if \a on is \c false. Returns a reference to this object. + \a on is \c false. Returns a reference to this object. */ /*! From 8ce7441892b1e089a1836334f5f71130930d28eb Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 3 Feb 2016 16:10:33 +0100 Subject: [PATCH 087/118] QFontEngineFT: Fix Clang warning about using uninitialized variables. gui/text/qfontengine_ft.cpp(1743,5) : warning: variable 'bytesPerLine' is used uninitialized whenever switch default is taken [-Wsometimes-uninitialized] gui/text/qfontengine_ft.cpp(1743,5) : warning: variable 'format' is used uninitialized whenever switch default is taken [-Wsometimes-uninitialized] The default branch is marked Q_UNREACHABLE, but apparently Clang does not recognize it. Task-number: QTBUG-50804 Change-Id: Idfce8cb2b9a481dd67a18d9952b920ad4f71e0f4 Reviewed-by: Konstantin Ritt --- src/gui/text/qfontengine_ft.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index de5bec6f93..0a0e174343 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -1719,8 +1719,8 @@ static inline QImage alphaMapFromGlyphData(QFontEngineFT::Glyph *glyph, QFontEng if (glyph == Q_NULLPTR) return QImage(); - QImage::Format format; - int bytesPerLine; + QImage::Format format = QImage::Format_Invalid; + int bytesPerLine = -1; switch (glyphFormat) { case QFontEngine::Format_Mono: format = QImage::Format_Mono; From 6129aade0018437d8d65a0051040d7100c8ec681 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Sat, 20 Feb 2016 22:50:23 +0100 Subject: [PATCH 088/118] QListWidget: setup connections when changing selection model. QListWidget uses a set of slots for its selection model that are connected only at creation time. This patch adds the missing connections cleanup and setup when a user changes the selection model. Task-number: QTBUG-50891 Change-Id: I942bae6c471ea1ae22637d09b96d6fbd422f653f Reviewed-by: Marc Mutz --- src/widgets/itemviews/qlistwidget.cpp | 29 ++++++++++++++++--- src/widgets/itemviews/qlistwidget.h | 2 ++ .../itemviews/qlistwidget/tst_qlistwidget.cpp | 26 +++++++++++++++++ 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp index 1f129e483b..434e819d9c 100644 --- a/src/widgets/itemviews/qlistwidget.cpp +++ b/src/widgets/itemviews/qlistwidget.cpp @@ -1069,10 +1069,6 @@ void QListWidgetPrivate::setup() QObject::connect(q, SIGNAL(entered(QModelIndex)), q, SLOT(_q_emitItemEntered(QModelIndex))); QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), q, SLOT(_q_emitItemChanged(QModelIndex))); - QObject::connect(q->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), - q, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex))); - QObject::connect(q->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - q, SIGNAL(itemSelectionChanged())); QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), q, SLOT(_q_dataChanged(QModelIndex,QModelIndex))); QObject::connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)), q, SLOT(_q_sort())); @@ -1354,6 +1350,31 @@ QListWidget::~QListWidget() { } +/*! + \reimp +*/ + +void QListWidget::setSelectionModel(QItemSelectionModel *selectionModel) +{ + Q_D(QListWidget); + + if (d->selectionModel) { + QObject::disconnect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)), + this, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex))); + QObject::disconnect(d->selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + this, SIGNAL(itemSelectionChanged())); + } + + QListView::setSelectionModel(selectionModel); + + if (d->selectionModel) { + QObject::connect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)), + this, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex))); + QObject::connect(d->selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + this, SIGNAL(itemSelectionChanged())); + } +} + /*! Returns the item that occupies the given \a row in the list if one has been set; otherwise returns 0. diff --git a/src/widgets/itemviews/qlistwidget.h b/src/widgets/itemviews/qlistwidget.h index ed85dbac5d..06e2469398 100644 --- a/src/widgets/itemviews/qlistwidget.h +++ b/src/widgets/itemviews/qlistwidget.h @@ -207,6 +207,8 @@ public: explicit QListWidget(QWidget *parent = Q_NULLPTR); ~QListWidget(); + void setSelectionModel(QItemSelectionModel *selectionModel) Q_DECL_OVERRIDE; + QListWidgetItem *item(int row) const; int row(const QListWidgetItem *item) const; void insertItem(int row, QListWidgetItem *item); diff --git a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp index 84b00147ca..e8bd86bee5 100644 --- a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp +++ b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp @@ -115,6 +115,7 @@ private slots: void QTBUG8086_currentItemChangedOnClick(); void QTBUG14363_completerWithAnyKeyPressedEditTriggers(); void mimeData(); + void QTBUG50891_ensureSelectionModelSignalConnectionsAreSet(); protected slots: void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last) @@ -1700,5 +1701,30 @@ void tst_QListWidget::mimeData() delete data2; } +void tst_QListWidget::QTBUG50891_ensureSelectionModelSignalConnectionsAreSet() +{ + qRegisterMetaType("QListWidgetItem*"); + QListWidget list; + for (int i = 0 ; i < 4; ++i) + new QListWidgetItem(QString::number(i), &list); + + list.setSelectionModel(new QItemSelectionModel(list.model())); + list.show(); + + QSignalSpy currentItemChangedSpy(&list, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*))); + QSignalSpy itemSelectionChangedSpy(&list, SIGNAL(itemSelectionChanged())); + + QVERIFY(QTest::qWaitForWindowExposed(&list)); + + QCOMPARE(currentItemChangedSpy.count(), 0); + QCOMPARE(itemSelectionChangedSpy.count(), 0); + + QTest::mouseClick(list.viewport(), Qt::LeftButton, 0, list.visualItemRect(list.item(2)).center()); + + QCOMPARE(currentItemChangedSpy.count(), 1); + QCOMPARE(itemSelectionChangedSpy.count(), 1); + +} + QTEST_MAIN(tst_QListWidget) #include "tst_qlistwidget.moc" From eec3aa499a6d8392566aeb5ab36d98c68b3400bf Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Fri, 19 Feb 2016 15:16:31 +0100 Subject: [PATCH 089/118] Doc: Evaluate QT_VERSION >= QT_VERSION_CHECK(6,0,0) to false This check is used in many places in the public header files, and correctly documenting the affected declarations depend on QDoc evaluating it correctly. As QDoc currently cannot evaluate complex preprocessor directives, work around this by explicitly evaluating the version check to false. Change-Id: If22eff76f6831c92375d9a0b25d04aa46422da13 Task-number: QTBUG-51262 Reviewed-by: Martin Smith --- doc/global/qt-cpp-defines.qdocconf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/global/qt-cpp-defines.qdocconf b/doc/global/qt-cpp-defines.qdocconf index 967bbb8ede..54d2cbbe4e 100644 --- a/doc/global/qt-cpp-defines.qdocconf +++ b/doc/global/qt-cpp-defines.qdocconf @@ -161,3 +161,7 @@ Cpp.ignoredirectives += \ QT_WARNING_DISABLE_MSVC \ Q_ATTRIBUTE_FORMAT_PRINTF \ Q_MV_IOS + +# Qt 6: Remove +falsehoods += \ + "QT_VERSION >= QT_VERSION_CHECK\\(6,0,0\\)" From fc6d5ed18da29138494803baa11c0edc22ace7f4 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 3 Feb 2016 12:45:21 +0100 Subject: [PATCH 090/118] QFileDialogOptions: Expose default name filter setting. Move the bool QFileDialogPrivate::defaultFileTypes to QFileDialogOptions as defaultNameFilters and add a static function returning the translated default filter string. Let QFileDialogOptions::nameFilters() return the default filter until a value has been set. This removes the need for special handling for empty filter lists in the QPA plugins. As a side effect, Qt Quick Controls's FileDialog will then also default to "All files" if no filters have been set. Task-number: QTBUG-50644 Change-Id: I9ba271a472d4fa03767b540ef6f1399f5ca4408e Reviewed-by: Richard Moe Gustavsen --- src/gui/kernel/qplatformdialoghelper.cpp | 41 ++++++++++++++++++++++-- src/gui/kernel/qplatformdialoghelper.h | 5 +++ src/widgets/dialogs/qfiledialog.cpp | 6 ++-- src/widgets/dialogs/qfiledialog_p.h | 1 - 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp index af0d71a57a..f2a1d20d54 100644 --- a/src/gui/kernel/qplatformdialoghelper.cpp +++ b/src/gui/kernel/qplatformdialoghelper.cpp @@ -39,6 +39,7 @@ #include "qplatformdialoghelper.h" +#include #include #include #include @@ -411,7 +412,8 @@ public: viewMode(QFileDialogOptions::Detail), fileMode(QFileDialogOptions::AnyFile), acceptMode(QFileDialogOptions::AcceptOpen), - filters(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs) + filters(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs), + useDefaultNameFilters(true) {} QFileDialogOptions::FileDialogOptions options; @@ -423,6 +425,7 @@ public: QString labels[QFileDialogOptions::DialogLabelCount]; QDir::Filters filters; QList sidebarUrls; + bool useDefaultNameFilters; QStringList nameFilters; QStringList mimeTypeFilters; QString defaultSuffix; @@ -534,14 +537,48 @@ QList QFileDialogOptions::sidebarUrls() const return d->sidebarUrls; } +/*! + \since 5.7 + \internal + The bool property useDefaultNameFilters indicates that no name filters have been + set or that they are equivalent to \gui{All Files (*)}. If it is true, the + platform can choose to hide the filter combo box. + + \sa defaultNameFilterString(). +*/ +bool QFileDialogOptions::useDefaultNameFilters() const +{ + return d->useDefaultNameFilters; +} + +void QFileDialogOptions::setUseDefaultNameFilters(bool dnf) +{ + d->useDefaultNameFilters = dnf; +} + void QFileDialogOptions::setNameFilters(const QStringList &filters) { + d->useDefaultNameFilters = filters.size() == 1 + && filters.first() == QFileDialogOptions::defaultNameFilterString(); d->nameFilters = filters; } QStringList QFileDialogOptions::nameFilters() const { - return d->nameFilters; + return d->useDefaultNameFilters ? + QStringList(QFileDialogOptions::defaultNameFilterString()) : d->nameFilters; +} + +/*! + \since 5.6 + \internal + \return The translated default name filter string (\gui{All Files (*)}). + \sa defaultNameFilters(), nameFilters() +*/ + +QString QFileDialogOptions::defaultNameFilterString() +{ + return QCoreApplication::translate("QFileDialog", "All Files (*)"); } void QFileDialogOptions::setMimeTypeFilters(const QStringList &filters) diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h index d0594593dd..825dcf293d 100644 --- a/src/gui/kernel/qplatformdialoghelper.h +++ b/src/gui/kernel/qplatformdialoghelper.h @@ -349,6 +349,9 @@ public: void setSidebarUrls(const QList &urls); QList sidebarUrls() const; + bool useDefaultNameFilters() const; + void setUseDefaultNameFilters(bool d); + void setNameFilters(const QStringList &filters); QStringList nameFilters() const; @@ -377,6 +380,8 @@ public: void setSupportedSchemes(const QStringList &schemes); QStringList supportedSchemes() const; + static QString defaultNameFilterString(); + private: QSharedDataPointer d; }; diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 07422f8811..4d74292e8f 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -532,7 +532,6 @@ QFileDialogPrivate::QFileDialogPrivate() deleteAction(0), showHiddenAction(0), useDefaultCaption(true), - defaultFileTypes(true), qFileDialogUi(0), options(new QFileDialogOptions) { @@ -663,8 +662,8 @@ void QFileDialogPrivate::retranslateStrings() { Q_Q(QFileDialog); /* WIDGETS */ - if (defaultFileTypes) - q->setNameFilter(QFileDialog::tr("All Files (*)")); + if (options->useDefaultNameFilters()) + q->setNameFilter(QFileDialogOptions::defaultNameFilterString()); if (nativeDialogInUse) return; @@ -1400,7 +1399,6 @@ QStringList qt_strip_filters(const QStringList &filters) void QFileDialog::setNameFilters(const QStringList &filters) { Q_D(QFileDialog); - d->defaultFileTypes = (filters == QStringList(QFileDialog::tr("All Files (*)"))); QStringList cleanedFilters; const int numFilters = filters.count(); cleanedFilters.reserve(numFilters); diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h index 84831ac03e..f273a4fb37 100644 --- a/src/widgets/dialogs/qfiledialog_p.h +++ b/src/widgets/dialogs/qfiledialog_p.h @@ -250,7 +250,6 @@ public: QAction *newFolderAction; bool useDefaultCaption; - bool defaultFileTypes; // setVisible_sys returns true if it ends up showing a native // dialog. Returning false means that a non-native dialog must be From 0ac8c8698c61a52fc98d8a8498982f68e3f87e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simo=20F=C3=A4lt?= Date: Mon, 15 Feb 2016 15:39:39 +0200 Subject: [PATCH 091/118] Autotest: Blacklist tst_QFontDialog::setFont() This test fails in distros using GNOME due to most likely bad usage of native dialogs. Task-number: QTBUG-51148 Change-Id: I6e539b429266e298ce413565e0191bffa7fbe6bc Reviewed-by: Simon Hausmann --- tests/auto/widgets/dialogs/qfontdialog/BLACKLIST | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/widgets/dialogs/qfontdialog/BLACKLIST b/tests/auto/widgets/dialogs/qfontdialog/BLACKLIST index ae0f7bb868..5fd026537e 100644 --- a/tests/auto/widgets/dialogs/qfontdialog/BLACKLIST +++ b/tests/auto/widgets/dialogs/qfontdialog/BLACKLIST @@ -4,3 +4,4 @@ rhel-7.1 [setFont] ubuntu-14.04 redhatenterpriselinuxworkstation-6.6 +rhel-7.1 From b8f89d8ef3f695746a8a48084d8ea710eb508d3d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 22 Feb 2016 16:23:39 +0100 Subject: [PATCH 092/118] Windows QPA: Use window flags stored in QWindowsWindow for frame geometry. Querying the flags of the QWindow fails when inside QWindowsWindow::setWindowFlags() since the new flags do not take effect. Task-number: QTBUG-40578 Task-number: QTBUG-51224 Change-Id: Ida8c23b64ddfde34ebc0af95c84954e666865240 Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowswindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 2ff71d827b..cb733ed5bd 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1914,7 +1914,7 @@ QMargins QWindowsWindow::frameMargins() const // Always skip calculating style-dependent margins for windows claimed to be frameless. // This allows users to remove the margins by handling WM_NCCALCSIZE with WS_THICKFRAME set // to ensure Areo snap still works (QTBUG-40578). - m_data.frame = window()->flags() & Qt::FramelessWindowHint + m_data.frame = m_data.flags & Qt::FramelessWindowHint ? QMargins(0, 0, 0, 0) : QWindowsGeometryHint::frame(style(), exStyle()); clearFlag(FrameDirty); From 20a29fbfe834c108517a23db359827d067246ecd Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 11 Feb 2016 09:48:06 +0100 Subject: [PATCH 093/118] Windows QPA: Send synthesized expose events when window shrinks. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the condition to check for plain move events and gain in one dimension in which case Windows will send events. Task-number: QTBUG-51038 Change-Id: I60433657f37275ee302f745291e79e465d52064d Reviewed-by: Błażej Szczygieł Reviewed-by: Shawn Rutledge --- src/plugins/platforms/windows/qwindowswindow.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index cb733ed5bd..e2f5885047 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1467,7 +1467,9 @@ void QWindowsWindow::handleGeometryChange() // QTBUG-32121: OpenGL/normal windows (with exception of ANGLE) do not receive // expose events when shrinking, synthesize. if (!testFlag(OpenGL_ES2) && isExposed() - && !(m_data.geometry.width() >= previousGeometry.width() || m_data.geometry.height() >= previousGeometry.height())) { + && m_data.geometry.size() != previousGeometry.size() // Exclude plain move + // One dimension grew -> Windows will send expose, no need to synthesize. + && !(m_data.geometry.width() > previousGeometry.width() || m_data.geometry.height() > previousGeometry.height())) { fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), true); } if (previousGeometry.topLeft() != m_data.geometry.topLeft()) { From eadd7e9cfb4e0802aa9da63badc41c39fec219bb Mon Sep 17 00:00:00 2001 From: Hannah von Reth Date: Tue, 16 Feb 2016 12:41:11 +0100 Subject: [PATCH 094/118] Set QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO for win32-g++ The win32-g++ mkspec is not based on gcc-base, so QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO is not inherited. Therefore, -release -force-debug-info would build with neither -O2 nor -g. Change-Id: I4e97cb08f577062dd342fb3e91c02adfd636a310 Reviewed-by: Oswald Buddenhagen --- mkspecs/win32-g++/qmake.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/mkspecs/win32-g++/qmake.conf b/mkspecs/win32-g++/qmake.conf index 61963c7b0d..2b9eab3e3d 100644 --- a/mkspecs/win32-g++/qmake.conf +++ b/mkspecs/win32-g++/qmake.conf @@ -31,6 +31,7 @@ QMAKE_CFLAGS_DEPS = -M QMAKE_CFLAGS_WARN_ON = -Wall -Wextra QMAKE_CFLAGS_WARN_OFF = -w QMAKE_CFLAGS_RELEASE = -O2 +QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO = -O2 -g QMAKE_CFLAGS_DEBUG = -g QMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses QMAKE_CFLAGS_SPLIT_SECTIONS = -ffunction-sections From 950bb7185c320ca9fe776bf0dc2a9589bf193a0d Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Tue, 2 Feb 2016 11:41:22 +0100 Subject: [PATCH 095/118] Autotests: if cross-compiling, ignore dbus status on compilation host The auto.pro file would bail out or skip based on the availability of the session bus at qmake time. That does not make sense for cross compilation: the session bus may be available on the target even if it is not on the compilation host. Change-Id: I459a518f3411acb39e8dcdad9d32ded1f9b57029 Reviewed-by: Thiago Macieira --- tests/auto/auto.pro | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index e905a416a6..ad7998a198 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -29,9 +29,10 @@ cross_compile: SUBDIRS -= tools cmake installed_cma !qtHaveModule(printsupport): SUBDIRS -= printsupport !qtHaveModule(concurrent): SUBDIRS -= concurrent !qtHaveModule(network): SUBDIRS -= network +!qtHaveModule(dbus): SUBDIRS -= dbus # Disable the QtDBus tests if we can't connect to the session bus -qtHaveModule(dbus) { +!cross_compile:qtHaveModule(dbus) { !system("dbus-send --session --type=signal / local.AutotestCheck.Hello >/dev/null 2>&1") { contains(QT_CONFIG, dbus-linked): \ error("QtDBus is enabled but session bus is not available. Please check the installation.") @@ -39,6 +40,4 @@ qtHaveModule(dbus) { warning("QtDBus is enabled with runtime support, but session bus is not available. Skipping QtDBus tests.") SUBDIRS -= dbus } -} else { - SUBDIRS -= dbus } From b6a824d0a3b4fabd9c22fe4c954d50e8755fb509 Mon Sep 17 00:00:00 2001 From: Dmitry Shachnev Date: Fri, 15 Jan 2016 17:04:01 +0300 Subject: [PATCH 096/118] Add native support for D-Bus global menu The protocol was originally developed by Canonical, currently supported by Unity and Plasma. Adjust some tests to use the non-native menu bar when they require it. [ChangeLog][XCB / X11] QMenuBar uses the unified D-Bus AppMenu menubar when the desktop environment supports it. Change-Id: Iea74b40522573bcc4f70168fe7fa2a49b4f3fc21 Reviewed-by: Shawn Rutledge --- .../com.canonical.AppMenu.Registrar.xml | 56 ++++++ src/platformsupport/dbusmenu/dbusmenu.pri | 4 + src/platformsupport/dbusmenu/qdbusmenubar.cpp | 172 ++++++++++++++++++ src/platformsupport/dbusmenu/qdbusmenubar_p.h | 91 +++++++++ .../dbusmenu/qdbusmenuregistrarproxy.cpp | 64 +++++++ .../dbusmenu/qdbusmenuregistrarproxy_p.h | 127 +++++++++++++ .../themes/genericunix/qgenericunixthemes.cpp | 68 ++++++- .../themes/genericunix/qgenericunixthemes_p.h | 12 ++ .../qaccessibility/tst_qaccessibility.cpp | 1 + .../widgets/widgets/qmdiarea/tst_qmdiarea.cpp | 5 +- .../qmdisubwindow/tst_qmdisubwindow.cpp | 5 +- .../auto/widgets/widgets/qmenu/tst_qmenu.cpp | 1 + .../widgets/widgets/qmenubar/tst_qmenubar.cpp | 5 + 13 files changed, 607 insertions(+), 4 deletions(-) create mode 100644 src/3rdparty/dbus-ifaces/com.canonical.AppMenu.Registrar.xml create mode 100644 src/platformsupport/dbusmenu/qdbusmenubar.cpp create mode 100644 src/platformsupport/dbusmenu/qdbusmenubar_p.h create mode 100644 src/platformsupport/dbusmenu/qdbusmenuregistrarproxy.cpp create mode 100644 src/platformsupport/dbusmenu/qdbusmenuregistrarproxy_p.h diff --git a/src/3rdparty/dbus-ifaces/com.canonical.AppMenu.Registrar.xml b/src/3rdparty/dbus-ifaces/com.canonical.AppMenu.Registrar.xml new file mode 100644 index 0000000000..42a71707b6 --- /dev/null +++ b/src/3rdparty/dbus-ifaces/com.canonical.AppMenu.Registrar.xml @@ -0,0 +1,56 @@ + + + + + + An interface to register a menu from an application's window to be displayed in another + window.  This manages that association between XWindow Window IDs and the dbus + address and object that provides the menu using the dbusmenu dbus interface. + + + + + The XWindow ID of the window + + + The object on the dbus interface implementing the dbusmenu interface + + + + + A method to allow removing a window from the database. Windows will also be removed + when the client drops off DBus so this is not required. It is polite though. And + important for testing. + + + The XWindow ID of the window + + + + Gets the registered menu for a given window ID. + + The XWindow ID of the window to get + + + The address of the connection on DBus (e.g. :1.23 or org.example.service) + + + The path to the object which implements the com.canonical.dbusmenu interface. + + + + diff --git a/src/platformsupport/dbusmenu/dbusmenu.pri b/src/platformsupport/dbusmenu/dbusmenu.pri index 9ca1f13897..2d0feca1a2 100644 --- a/src/platformsupport/dbusmenu/dbusmenu.pri +++ b/src/platformsupport/dbusmenu/dbusmenu.pri @@ -6,10 +6,14 @@ HEADERS += \ $$PWD/qdbusmenuadaptor_p.h \ $$PWD/qdbusmenutypes_p.h \ $$PWD/qdbusmenuconnection_p.h \ + $$PWD/qdbusmenubar_p.h \ + $$PWD/qdbusmenuregistrarproxy_p.h \ $$PWD/qdbusplatformmenu_p.h \ SOURCES += \ $$PWD/qdbusmenuadaptor.cpp \ $$PWD/qdbusmenutypes.cpp \ $$PWD/qdbusmenuconnection.cpp \ + $$PWD/qdbusmenubar.cpp \ + $$PWD/qdbusmenuregistrarproxy.cpp \ $$PWD/qdbusplatformmenu.cpp \ diff --git a/src/platformsupport/dbusmenu/qdbusmenubar.cpp b/src/platformsupport/dbusmenu/qdbusmenubar.cpp new file mode 100644 index 0000000000..7d53de6db4 --- /dev/null +++ b/src/platformsupport/dbusmenu/qdbusmenubar.cpp @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Dmitry Shachnev +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** 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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdbusmenubar_p.h" +#include "qdbusmenuregistrarproxy_p.h" + +QT_BEGIN_NAMESPACE + +/* note: do not change these to QStringLiteral; + we are unloaded before QtDBus is done using the strings. + */ +#define REGISTRAR_SERVICE QLatin1String("com.canonical.AppMenu.Registrar") +#define REGISTRAR_PATH QLatin1String("/com/canonical/AppMenu/Registrar") + +QDBusMenuBar::QDBusMenuBar() + : QPlatformMenuBar() + , m_menu(new QDBusPlatformMenu()) + , m_menuAdaptor(new QDBusMenuAdaptor(m_menu)) + , m_windowId(0) +{ + QDBusMenuItem::registerDBusTypes(); + connect(m_menu, &QDBusPlatformMenu::propertiesUpdated, + m_menuAdaptor, &QDBusMenuAdaptor::ItemsPropertiesUpdated); + connect(m_menu, &QDBusPlatformMenu::updated, + m_menuAdaptor, &QDBusMenuAdaptor::LayoutUpdated); +} + +QDBusMenuBar::~QDBusMenuBar() +{ + unregisterMenuBar(); + delete m_menuAdaptor; + delete m_menu; + qDeleteAll(m_menuItems); +} + +QDBusPlatformMenuItem *QDBusMenuBar::menuItemForMenu(QPlatformMenu *menu) +{ + if (!menu) + return nullptr; + quintptr tag = menu->tag(); + const auto it = m_menuItems.constFind(tag); + if (it != m_menuItems.cend()) { + return *it; + } else { + QDBusPlatformMenuItem *item = new QDBusPlatformMenuItem; + updateMenuItem(item, menu); + m_menuItems.insert(tag, item); + return item; + } +} + +void QDBusMenuBar::updateMenuItem(QDBusPlatformMenuItem *item, QPlatformMenu *menu) +{ + const QDBusPlatformMenu *ourMenu = qobject_cast(menu); + item->setText(ourMenu->text()); + item->setIcon(ourMenu->icon()); + item->setEnabled(ourMenu->isEnabled()); + item->setVisible(ourMenu->isVisible()); + item->setMenu(menu); +} + +void QDBusMenuBar::insertMenu(QPlatformMenu *menu, QPlatformMenu *before) +{ + QDBusPlatformMenuItem *menuItem = menuItemForMenu(menu); + QDBusPlatformMenuItem *beforeItem = menuItemForMenu(before); + m_menu->insertMenuItem(menuItem, beforeItem); + m_menu->emitUpdated(); +} + +void QDBusMenuBar::removeMenu(QPlatformMenu *menu) +{ + QDBusPlatformMenuItem *menuItem = menuItemForMenu(menu); + m_menu->removeMenuItem(menuItem); + m_menu->emitUpdated(); +} + +void QDBusMenuBar::syncMenu(QPlatformMenu *menu) +{ + QDBusPlatformMenuItem *menuItem = menuItemForMenu(menu); + updateMenuItem(menuItem, menu); +} + +void QDBusMenuBar::handleReparent(QWindow *newParentWindow) +{ + if (newParentWindow && newParentWindow->winId() != m_windowId) { + unregisterMenuBar(); + m_windowId = newParentWindow->winId(); + registerMenuBar(); + } +} + +QPlatformMenu *QDBusMenuBar::menuForTag(quintptr tag) const +{ + QDBusPlatformMenuItem *menuItem = m_menuItems.value(tag); + if (menuItem) + return const_cast(menuItem->menu()); + return nullptr; +} + +void QDBusMenuBar::registerMenuBar() +{ + static uint menuBarId = 0; + + QDBusConnection connection = QDBusConnection::sessionBus(); + m_objectPath = QStringLiteral("/MenuBar/%1").arg(++menuBarId); + if (!connection.registerObject(m_objectPath, m_menu)) + return; + + QDBusMenuRegistrarInterface registrar(REGISTRAR_SERVICE, REGISTRAR_PATH, connection, this); + QDBusPendingReply<> r = registrar.RegisterWindow(m_windowId, QDBusObjectPath(m_objectPath)); + r.waitForFinished(); + if (r.isError()) { + qWarning("Failed to register window menu, reason: %s (\"%s\")", + qUtf8Printable(r.error().name()), qUtf8Printable(r.error().message())); + connection.unregisterObject(m_objectPath); + } +} + +void QDBusMenuBar::unregisterMenuBar() +{ + QDBusConnection connection = QDBusConnection::sessionBus(); + + if (m_windowId) { + QDBusMenuRegistrarInterface registrar(REGISTRAR_SERVICE, REGISTRAR_PATH, connection, this); + QDBusPendingReply<> r = registrar.UnregisterWindow(m_windowId); + r.waitForFinished(); + if (r.isError()) + qWarning("Failed to unregister window menu, reason: %s (\"%s\")", + qUtf8Printable(r.error().name()), qUtf8Printable(r.error().message())); + } + + if (!m_objectPath.isEmpty()) + connection.unregisterObject(m_objectPath); +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/dbusmenu/qdbusmenubar_p.h b/src/platformsupport/dbusmenu/qdbusmenubar_p.h new file mode 100644 index 0000000000..157befe9e3 --- /dev/null +++ b/src/platformsupport/dbusmenu/qdbusmenubar_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Dmitry Shachnev +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** 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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDBUSMENUBAR_P_H +#define QDBUSMENUBAR_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QDBusMenuBar : public QPlatformMenuBar +{ + Q_OBJECT + +public: + QDBusMenuBar(); + virtual ~QDBusMenuBar(); + + void insertMenu(QPlatformMenu *menu, QPlatformMenu *before) Q_DECL_OVERRIDE; + void removeMenu(QPlatformMenu *menu) Q_DECL_OVERRIDE; + void syncMenu(QPlatformMenu *menu) Q_DECL_OVERRIDE; + void handleReparent(QWindow *newParentWindow) Q_DECL_OVERRIDE; + QPlatformMenu *menuForTag(quintptr tag) const Q_DECL_OVERRIDE; + +private: + QDBusPlatformMenu *m_menu; + QDBusMenuAdaptor *m_menuAdaptor; + QHash m_menuItems; + uint m_windowId; + QString m_objectPath; + + QDBusPlatformMenuItem *menuItemForMenu(QPlatformMenu *menu); + static void updateMenuItem(QDBusPlatformMenuItem *item, QPlatformMenu *menu); + void registerMenuBar(); + void unregisterMenuBar(); +}; + +QT_END_NAMESPACE + +#endif // QDBUSMENUBAR_P_H diff --git a/src/platformsupport/dbusmenu/qdbusmenuregistrarproxy.cpp b/src/platformsupport/dbusmenu/qdbusmenuregistrarproxy.cpp new file mode 100644 index 0000000000..c59b5a675e --- /dev/null +++ b/src/platformsupport/dbusmenu/qdbusmenuregistrarproxy.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Dmitry Shachnev +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** 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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* + * This file was originally created by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -p qdbusmenuregistrarproxy ../../3rdparty/dbus-ifaces/com.canonical.AppMenu.Registrar.xml + * + * However it is maintained manually. + */ + +#include "qdbusmenuregistrarproxy_p.h" + +QT_BEGIN_NAMESPACE + +/* + * Implementation of interface class QDBusMenuRegistrarInterface + */ + +QDBusMenuRegistrarInterface::QDBusMenuRegistrarInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +QDBusMenuRegistrarInterface::~QDBusMenuRegistrarInterface() +{ +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/dbusmenu/qdbusmenuregistrarproxy_p.h b/src/platformsupport/dbusmenu/qdbusmenuregistrarproxy_p.h new file mode 100644 index 0000000000..c92de0a140 --- /dev/null +++ b/src/platformsupport/dbusmenu/qdbusmenuregistrarproxy_p.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Dmitry Shachnev +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** 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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* + * This file was originally created by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -p qdbusmenuregistrarproxy ../../3rdparty/dbus-ifaces/com.canonical.AppMenu.Registrar.xml + * + * However it is maintained manually. + */ + +#ifndef QDBUSMENUREGISTRARPROXY_P_H +#define QDBUSMENUREGISTRARPROXY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/* + * Proxy class for interface com.canonical.AppMenu.Registrar + */ +class QDBusMenuRegistrarInterface : public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { + return "com.canonical.AppMenu.Registrar"; + } + +public: + explicit QDBusMenuRegistrarInterface(const QString &service, + const QString &path, + const QDBusConnection &connection, + QObject *parent = nullptr); + + ~QDBusMenuRegistrarInterface(); + +public Q_SLOTS: // METHODS + QDBusPendingReply GetMenuForWindow(uint windowId) + { + QList argumentList; + argumentList << QVariant::fromValue(windowId); + return asyncCallWithArgumentList(QStringLiteral("GetMenuForWindow"), argumentList); + } + QDBusReply GetMenuForWindow(uint windowId, QDBusObjectPath &menuObjectPath) + { + QList argumentList; + argumentList << QVariant::fromValue(windowId); + QDBusMessage reply = callWithArgumentList(QDBus::Block, QStringLiteral("GetMenuForWindow"), argumentList); + QList arguments = reply.arguments(); + if (reply.type() == QDBusMessage::ReplyMessage && arguments.count() == 2) + menuObjectPath = qdbus_cast(arguments.at(1)); + return reply; + } + + QDBusPendingReply<> RegisterWindow(uint windowId, const QDBusObjectPath &menuObjectPath) + { + QList argumentList; + argumentList << QVariant::fromValue(windowId) << QVariant::fromValue(menuObjectPath); + return asyncCallWithArgumentList(QStringLiteral("RegisterWindow"), argumentList); + } + + QDBusPendingReply<> UnregisterWindow(uint windowId) + { + QList argumentList; + argumentList << QVariant::fromValue(windowId); + return asyncCallWithArgumentList(QStringLiteral("UnregisterWindow"), argumentList); + } +}; + +QT_END_NAMESPACE + +#endif // QDBUSMENUREGISTRARPROXY_P_H diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp index 026ba11c3d..aee12eed76 100644 --- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp +++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp @@ -59,9 +59,12 @@ #include #include #include +#ifndef QT_NO_DBUS +#include "QtPlatformSupport/private/qdbusplatformmenu_p.h" +#include "QtPlatformSupport/private/qdbusmenubar_p.h" +#endif #if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON) #include "QtPlatformSupport/private/qdbustrayicon_p.h" -#include "QtPlatformSupport/private/qdbusplatformmenu_p.h" #endif #include @@ -114,6 +117,21 @@ static bool isDBusTrayAvailable() { } #endif +#ifndef QT_NO_DBUS +static bool checkDBusGlobalMenuAvailable() +{ + QDBusConnection connection = QDBusConnection::sessionBus(); + QString registrarService = QStringLiteral("com.canonical.AppMenu.Registrar"); + return connection.interface()->isServiceRegistered(registrarService); +} + +static bool isDBusGlobalMenuAvailable() +{ + static bool dbusGlobalMenuAvailable = checkDBusGlobalMenuAvailable(); + return dbusGlobalMenuAvailable; +} +#endif + class QGenericUnixThemePrivate : public QPlatformThemePrivate { public: @@ -172,6 +190,22 @@ QStringList QGenericUnixTheme::xdgIconThemePaths() return paths; } +#ifndef QT_NO_DBUS +QPlatformMenu *QGenericUnixTheme::createPlatformMenu() const +{ + if (isDBusGlobalMenuAvailable()) + return new QDBusPlatformMenu(); + return nullptr; +} + +QPlatformMenuBar *QGenericUnixTheme::createPlatformMenuBar() const +{ + if (isDBusGlobalMenuAvailable()) + return new QDBusMenuBar(); + return nullptr; +} +#endif + #if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON) QPlatformSystemTrayIcon *QGenericUnixTheme::createPlatformSystemTrayIcon() const { @@ -559,6 +593,22 @@ QPlatformTheme *QKdeTheme::createKdeTheme() return new QKdeTheme(kdeDirs, kdeVersion); } +#ifndef QT_NO_DBUS +QPlatformMenu *QKdeTheme::createPlatformMenu() const +{ + if (isDBusGlobalMenuAvailable()) + return new QDBusPlatformMenu(); + return nullptr; +} + +QPlatformMenuBar *QKdeTheme::createPlatformMenuBar() const +{ + if (isDBusGlobalMenuAvailable()) + return new QDBusMenuBar(); + return nullptr; +} +#endif + #if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON) QPlatformSystemTrayIcon *QKdeTheme::createPlatformSystemTrayIcon() const { @@ -655,6 +705,22 @@ QString QGnomeTheme::gtkFontName() const return QStringLiteral("%1 %2").arg(QLatin1String(defaultSystemFontNameC)).arg(defaultSystemFontSize); } +#ifndef QT_NO_DBUS +QPlatformMenu *QGnomeTheme::createPlatformMenu() const +{ + if (isDBusGlobalMenuAvailable()) + return new QDBusPlatformMenu(); + return nullptr; +} + +QPlatformMenuBar *QGnomeTheme::createPlatformMenuBar() const +{ + if (isDBusGlobalMenuAvailable()) + return new QDBusMenuBar(); + return nullptr; +} +#endif + #if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON) QPlatformSystemTrayIcon *QGnomeTheme::createPlatformSystemTrayIcon() const { diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h index 2d46a4d95e..b7e0d53d6f 100644 --- a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h +++ b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h @@ -85,6 +85,10 @@ public: QVariant themeHint(ThemeHint hint) const Q_DECL_OVERRIDE; static QStringList xdgIconThemePaths(); +#ifndef QT_NO_DBUS + QPlatformMenu *createPlatformMenu() const Q_DECL_OVERRIDE; + QPlatformMenuBar *createPlatformMenuBar() const Q_DECL_OVERRIDE; +#endif #if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON) QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const Q_DECL_OVERRIDE; #endif @@ -107,6 +111,10 @@ public: const QPalette *palette(Palette type = SystemPalette) const Q_DECL_OVERRIDE; const QFont *font(Font type) const Q_DECL_OVERRIDE; +#ifndef QT_NO_DBUS + QPlatformMenu *createPlatformMenu() const Q_DECL_OVERRIDE; + QPlatformMenuBar *createPlatformMenuBar() const Q_DECL_OVERRIDE; +#endif #if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON) QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const Q_DECL_OVERRIDE; #endif @@ -127,6 +135,10 @@ public: QString standardButtonText(int button) const Q_DECL_OVERRIDE; virtual QString gtkFontName() const; +#ifndef QT_NO_DBUS + QPlatformMenu *createPlatformMenu() const Q_DECL_OVERRIDE; + QPlatformMenuBar *createPlatformMenuBar() const Q_DECL_OVERRIDE; +#endif #if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON) QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const Q_DECL_OVERRIDE; #endif diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index 023f800d29..99e3fc5bf2 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -1411,6 +1411,7 @@ void tst_QAccessibility::menuTest() { QMainWindow mw; mw.resize(300, 200); + mw.menuBar()->setNativeMenuBar(false); QMenu *file = mw.menuBar()->addMenu("&File"); QMenu *fileNew = file->addMenu("&New..."); fileNew->menuAction()->setShortcut(tr("Ctrl+N")); diff --git a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp index 0fbe5bc86b..69dd45e72f 100644 --- a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp +++ b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp @@ -632,7 +632,7 @@ void tst_QMdiArea::changeWindowTitle() mw->setWindowTitle( mwc ); QMdiArea *ws = new QMdiArea( mw ); mw->setCentralWidget( ws ); - mw->menuBar(); + mw->menuBar()->setNativeMenuBar(false); mw->show(); QVERIFY(QTest::qWaitForWindowExposed(mw)); @@ -741,7 +741,7 @@ void tst_QMdiArea::changeModified() mw->setWindowTitle( mwc ); QMdiArea *ws = new QMdiArea( mw ); mw->setCentralWidget( ws ); - mw->menuBar(); + mw->menuBar()->setNativeMenuBar(false); mw->show(); QWidget *widget = new QWidget( ws ); @@ -2006,6 +2006,7 @@ void tst_QMdiArea::iconGeometryInMenuBar() #if !defined (Q_OS_MAC) && !defined(Q_OS_WINCE) QMainWindow mainWindow; QMenuBar *menuBar = mainWindow.menuBar(); + menuBar->setNativeMenuBar(false); QMdiArea *mdiArea = new QMdiArea; QMdiSubWindow *subWindow = mdiArea->addSubWindow(new QWidget); mainWindow.setCentralWidget(mdiArea); diff --git a/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp b/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp index b58d33ab4a..fe5c3a14a0 100644 --- a/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp +++ b/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp @@ -967,7 +967,7 @@ void tst_QMdiSubWindow::setSystemMenu() QMdiArea *mdiArea = new QMdiArea; mdiArea->addSubWindow(subWindow); mainWindow.setCentralWidget(mdiArea); - mainWindow.menuBar(); + mainWindow.menuBar()->setNativeMenuBar(false); mainWindow.show(); QVERIFY(QTest::qWaitForWindowExposed(&mainWindow)); QTest::qWait(60); @@ -1467,6 +1467,7 @@ void tst_QMdiSubWindow::hideAndShow() QMainWindow mainWindow; mainWindow.setGeometry(0, 0, 640, 480); QMenuBar *menuBar = mainWindow.menuBar(); + menuBar->setNativeMenuBar(false); mainWindow.setCentralWidget(tabWidget); mainWindow.show(); QVERIFY(QTest::qWaitForWindowExposed(&mainWindow)); @@ -1735,6 +1736,7 @@ void tst_QMdiSubWindow::replaceMenuBarWhileMaximized() mainWindow.setCentralWidget(mdiArea); QMenuBar *menuBar = mainWindow.menuBar(); + menuBar->setNativeMenuBar(false); mainWindow.show(); QVERIFY(QTest::qWaitForWindowExposed(&mainWindow)); @@ -1751,6 +1753,7 @@ void tst_QMdiSubWindow::replaceMenuBarWhileMaximized() // Replace. mainWindow.setMenuBar(new QMenuBar); menuBar = mainWindow.menuBar(); + menuBar->setNativeMenuBar(false); qApp->processEvents(); QVERIFY(subWindow->maximizedButtonsWidget()); diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp index a04978341b..8ed781a023 100644 --- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp +++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp @@ -447,6 +447,7 @@ void tst_QMenu::overrideMenuAction() //test the override menu action by first creating an action to which we set its menu QMainWindow w; w.resize(300, 200); + w.menuBar()->setNativeMenuBar(false); centerOnScreen(&w); QAction *aFileMenu = new QAction("&File", &w); diff --git a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp index ad7638650b..3bcdea3137 100644 --- a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp +++ b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp @@ -206,6 +206,7 @@ void tst_QMenuBar::cleanup() TestMenu tst_QMenuBar::initSimpleMenuBar(QMenuBar *mb) { TestMenu result; + mb->setNativeMenuBar(false); connect(mb, SIGNAL(triggered(QAction*)), this, SLOT(onSimpleActivated(QAction*))); QMenu *menu = mb->addMenu(QStringLiteral("&accel")); QAction *action = menu->addAction(QStringLiteral("menu1") ); @@ -273,6 +274,7 @@ void tst_QMenuBar::onComplexActionTriggered() TestMenu tst_QMenuBar::initComplexMenuBar(QMenuBar *mb) { TestMenu result; + mb->setNativeMenuBar(false); QMenu *menu = addNumberedMenu(mb, 1); result.menus << menu; for (char c = 'a'; c < 'c'; ++c) @@ -986,6 +988,7 @@ void tst_QMenuBar::check_altClosePress() QMainWindow w; w.setWindowTitle(QTest::currentTestFunction()); + w.menuBar()->setNativeMenuBar(false); QMenu *menuFile = w.menuBar()->addMenu(tr("&File")); menuFile->addAction("Quit"); QMenu *menuEdit = w.menuBar()->addMenu(tr("&Edit")); @@ -1061,6 +1064,7 @@ void tst_QMenuBar::check_menuPosition() menu.addAction("item"); } + w.menuBar()->setNativeMenuBar(false); QAction *menu_action = w.menuBar()->addMenu(&menu); centerOnScreen(&w); w.show(); @@ -1394,6 +1398,7 @@ void tst_QMenuBar::cornerWidgets() widget.setWindowTitle(QLatin1String(QTest::currentTestFunction()) + dataTag); QVBoxLayout *layout = new QVBoxLayout(&widget); QMenuBar *menuBar = new QMenuBar(&widget); + menuBar->setNativeMenuBar(false); layout->addWidget(menuBar); QMenu *fileMenu = menuBar->addMenu("File"); fileMenu->addAction("Quit"); From d392826959257c9e407fb32d1de62b0b56a2c052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Wed, 10 Feb 2016 19:02:40 +0100 Subject: [PATCH 097/118] Make it possible to preserve the library/plugin path in tst_selftest If QT_PRESERVE_TESTLIB_PATH is set, then LD_LIBRARY_PATH and QT_PLUGIN_PATH won't be filtered out for the sub-tests started by tst_selftest. Change-Id: Ic43ba9b4d882ee36b2f7495b1c880f26aefd2629 Reviewed-by: aavit --- tests/auto/testlib/selftests/tst_selftests.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp index 94002ec75b..0806077031 100644 --- a/tests/auto/testlib/selftests/tst_selftests.cpp +++ b/tests/auto/testlib/selftests/tst_selftests.cpp @@ -543,6 +543,7 @@ static QProcessEnvironment processEnvironment() static QProcessEnvironment result; if (result.isEmpty()) { const QProcessEnvironment systemEnvironment = QProcessEnvironment::systemEnvironment(); + const bool preserveLibPath = qEnvironmentVariableIsSet("QT_PRESERVE_TESTLIB_PATH"); foreach (const QString &key, systemEnvironment.keys()) { const bool useVariable = key == QLatin1String("PATH") || key == QLatin1String("QT_QPA_PLATFORM") #if defined(Q_OS_QNX) @@ -557,6 +558,8 @@ static QProcessEnvironment processEnvironment() #ifdef __COVERAGESCANNER__ || key == QLatin1String("QT_TESTCOCOON_ACTIVE") #endif + || ( preserveLibPath && (key == QLatin1String("QT_PLUGIN_PATH") + || key == QLatin1String("LD_LIBRARY_PATH"))) ; if (useVariable) result.insert(key, systemEnvironment.value(key)); From 57ecd5aeeb1f609206933be66b92fcdf703703d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Thu, 21 Jan 2016 13:19:37 +0100 Subject: [PATCH 098/118] QtWidgets: Proper delivery of enter/leave event to context menus First-level context menu grabs the mouse, so all mouse events are delivered to it. This menu passes the mouse events to submenus. Any platform delivers mouse enter/leave event differently when window is grabbed. This patch unifies event delivery to context menus - it can block some unwanted events and it emulates fake events if necessary. This patch can reduce duplicated events and can provide proper enter or leave event to additional widgets in the context menu. It can also prevent submenu from unwanted close on Windows and X11. Added autotest. Task-number: QTBUG-45565 Task-number: QTBUG-45893 Task-number: QTBUG-47515 Change-Id: I7dd476d0be23afa34e947e54aef235012d173dcf Reviewed-by: Shawn Rutledge --- src/widgets/kernel/qwidgetwindow.cpp | 54 +++++++-- .../auto/widgets/widgets/qmenu/tst_qmenu.cpp | 109 ++++++++++++++++++ 2 files changed, 151 insertions(+), 12 deletions(-) diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 0de0fe21f2..b2a2ecc3b9 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -313,6 +313,14 @@ QPointer qt_last_mouse_receiver = 0; void QWidgetWindow::handleEnterLeaveEvent(QEvent *event) { +#if !defined(Q_OS_OSX) && !defined(Q_OS_IOS) // Cocoa tracks popups + // Ignore all enter/leave events from QPA if we are not on the first-level context menu. + // This prevents duplicated events on most platforms. Fake events will be delivered in + // QWidgetWindow::handleMouseEvent(QMouseEvent *). Make an exception whether the widget + // is already under mouse - let the mouse leave. + if (QApplicationPrivate::inPopupMode() && m_widget != QApplication::activePopupWidget() && !m_widget->underMouse()) + return; +#endif if (event->type() == QEvent::Leave) { QWidget *enter = 0; // Check from window system event queue if the next queued enter targets a window @@ -407,14 +415,13 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) QEvent::MouseButtonRelease : QEvent::MouseButtonPress; if (qApp->d_func()->inPopupMode()) { QWidget *activePopupWidget = qApp->activePopupWidget(); - QWidget *popup = activePopupWidget; QPoint mapped = event->pos(); - if (popup != m_widget) - mapped = popup->mapFromGlobal(event->globalPos()); + if (activePopupWidget != m_widget) + mapped = activePopupWidget->mapFromGlobal(event->globalPos()); bool releaseAfter = false; - QWidget *popupChild = popup->childAt(mapped); + QWidget *popupChild = activePopupWidget->childAt(mapped); - if (popup != qt_popup_down) { + if (activePopupWidget != qt_popup_down) { qt_button_down = 0; qt_popup_down = 0; } @@ -423,7 +430,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) case QEvent::MouseButtonPress: case QEvent::MouseButtonDblClick: qt_button_down = popupChild; - qt_popup_down = popup; + qt_popup_down = activePopupWidget; break; case QEvent::MouseButtonRelease: releaseAfter = true; @@ -434,18 +441,41 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) int oldOpenPopupCount = openPopupCount; - if (popup->isEnabled()) { + if (activePopupWidget->isEnabled()) { // deliver event qt_replay_popup_mouse_event = false; - QWidget *receiver = popup; + QWidget *receiver = activePopupWidget; QPoint widgetPos = mapped; if (qt_button_down) receiver = qt_button_down; else if (popupChild) receiver = popupChild; - if (receiver != popup) + if (receiver != activePopupWidget) widgetPos = receiver->mapFromGlobal(event->globalPos()); - QWidget *alien = m_widget->childAt(m_widget->mapFromGlobal(event->globalPos())); + QWidget *alien = receiver; + +#if !defined(Q_OS_OSX) && !defined(Q_OS_IOS) // Cocoa tracks popups + const bool reallyUnderMouse = activePopupWidget->rect().contains(mapped); + const bool underMouse = activePopupWidget->underMouse(); + if (activePopupWidget != m_widget || (!underMouse && qt_button_down)) { + // If active popup menu is not the first-level popup menu then we must emulate enter/leave events, + // because first-level popup menu grabs the mouse and enter/leave events are delivered only to it + // by QPA. Make an exception for first-level popup menu when the mouse button is pressed on widget. + if (underMouse != reallyUnderMouse) { + if (reallyUnderMouse) { + QApplicationPrivate::dispatchEnterLeave(receiver, Q_NULLPTR, event->screenPos()); + qt_last_mouse_receiver = receiver; + } else { + QApplicationPrivate::dispatchEnterLeave(Q_NULLPTR, qt_last_mouse_receiver, event->screenPos()); + qt_last_mouse_receiver = receiver; + receiver = activePopupWidget; + } + } + } else if (!reallyUnderMouse) { + alien = Q_NULLPTR; + } +#endif + QMouseEvent e(event->type(), widgetPos, event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers(), event->source()); e.setTimestamp(event->timestamp()); @@ -457,7 +487,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) case QEvent::MouseButtonPress: case QEvent::MouseButtonDblClick: case QEvent::MouseButtonRelease: - popup->close(); + activePopupWidget->close(); break; default: break; @@ -503,7 +533,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) } else if (event->type() == contextMenuTrigger && event->button() == Qt::RightButton && (openPopupCount == oldOpenPopupCount)) { - QWidget *popupEvent = popup; + QWidget *popupEvent = activePopupWidget; if (qt_button_down) popupEvent = qt_button_down; else if(popupChild) diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp index b3f9c54f24..20f17f6e9e 100644 --- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp +++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp @@ -110,6 +110,9 @@ private slots: void QTBUG7411_submenus_activate(); void QTBUG30595_rtl_submenu(); void QTBUG20403_nested_popup_on_shortcut_trigger(); +#ifndef QT_NO_CURSOR + void QTBUG47515_widgetActionEnterLeave(); +#endif void QTBUG_10735_crashWithDialog(); #ifdef Q_OS_MAC void QTBUG_37933_ampersands_data(); @@ -1070,6 +1073,112 @@ void tst_QMenu::QTBUG20403_nested_popup_on_shortcut_trigger() QVERIFY(!subsub1.isVisible()); } +class MyWidget : public QWidget +{ +public: + MyWidget(QWidget *parent) : + QWidget(parent), + move(0), enter(0), leave(0) + { + setMinimumSize(100, 100); + setMouseTracking(true); + } + + bool event(QEvent *e) Q_DECL_OVERRIDE + { + switch (e->type()) { + case QEvent::MouseMove: + ++move; + break; + case QEvent::Enter: + ++enter; + break; + case QEvent::Leave: + ++leave; + break; + default: + break; + } + return QWidget::event(e); + } + + int move, enter, leave; +}; + +#ifndef QT_NO_CURSOR +void tst_QMenu::QTBUG47515_widgetActionEnterLeave() +{ + if (QGuiApplication::platformName() == QLatin1String("cocoa")) + QSKIP("This test fails on OS X on CI"); + + const QPoint center = QGuiApplication::primaryScreen()->availableGeometry().center(); + const QPoint cursorPos = center - QPoint(100, 100); + + QScopedPointer menu1(new QMenu("Menu1")); + QScopedPointer menu2(new QMenu("Menu2")); + + QWidgetAction *wA1 = new QWidgetAction(menu1.data()); + MyWidget *w1 = new MyWidget(menu1.data()); + wA1->setDefaultWidget(w1); + + QWidgetAction *wA2 = new QWidgetAction(menu2.data()); + MyWidget *w2 = new MyWidget(menu2.data()); + wA2->setDefaultWidget(w2); + + QAction *nextMenuAct = menu1->addMenu(menu2.data()); + + menu1->addAction(wA1); + menu2->addAction(wA2); + + // Root menu + { + QCursor::setPos(cursorPos); + QCoreApplication::processEvents(); + + menu1->popup(center); + QVERIFY(QTest::qWaitForWindowExposed(menu1.data())); + + QCursor::setPos(w1->mapToGlobal(w1->rect().center())); + QVERIFY(w1->isVisible()); + QTRY_COMPARE(w1->leave, 0); + QTRY_COMPARE(w1->enter, 1); + + // Check whether leave event is not delivered on mouse move + w1->move = 0; + QCursor::setPos(w1->mapToGlobal(w1->rect().center()) + QPoint(1, 1)); + QTRY_COMPARE(w1->move, 1); + QTRY_COMPARE(w1->leave, 0); + QTRY_COMPARE(w1->enter, 1); + + QCursor::setPos(cursorPos); + QTRY_COMPARE(w1->leave, 1); + QTRY_COMPARE(w1->enter, 1); + } + + // Submenu + { + menu1->setActiveAction(nextMenuAct); + QVERIFY(QTest::qWaitForWindowExposed(menu2.data())); + + QCursor::setPos(w2->mapToGlobal(w2->rect().center())); + QVERIFY(w2->isVisible()); + QTRY_COMPARE(w2->leave, 0); + QTRY_COMPARE(w2->enter, 1); + + // Check whether leave event is not delivered on mouse move + w2->move = 0; + QCursor::setPos(w2->mapToGlobal(w2->rect().center()) + QPoint(1, 1)); + QTRY_COMPARE(w2->move, 1); + QTRY_COMPARE(w2->leave, 0); + QTRY_COMPARE(w2->enter, 1); + + QCursor::setPos(cursorPos); + QTRY_COMPARE(w2->leave, 1); + QTRY_COMPARE(w2->enter, 1); + } +} +#endif // !QT_NO_CURSOR + class MyMenu : public QMenu { Q_OBJECT From ad9340de99a9961a8d34c7e430638a7c01c3d2be Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Wed, 17 Feb 2016 12:26:43 +0300 Subject: [PATCH 099/118] QListView: avoid quadratic complexity in selectedIndexes(). Use std::remove_if(), which is linear, instead of looping over erase(it), which turns the loop quadratic. Reorder condition: call cheap non-virtual QModelIndex::column() first, then virtuals parent(), and isIndexHidden(). Change-Id: Id46ee1297b91906332eeca98f69372ef887ac330 Reviewed-by: Marc Mutz Reviewed-by: Edward Welbourne --- src/widgets/itemviews/qlistview.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index 8e4d94d2f0..646ab58e3d 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -1440,13 +1440,11 @@ QModelIndexList QListView::selectedIndexes() const return QModelIndexList(); QModelIndexList viewSelected = d->selectionModel->selectedIndexes(); - 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; - else - viewSelected.removeAt(i); - } + auto ignorable = [this, d](const QModelIndex &index) { + return index.column() != d->column || index.parent() != d->root || isIndexHidden(index); + }; + viewSelected.erase(std::remove_if(viewSelected.begin(), viewSelected.end(), ignorable), + viewSelected.end()); return viewSelected; } From ea711d0f59d6272f14b61cb2fd3dc1ede2cc1eb6 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Sat, 20 Feb 2016 11:57:23 +0300 Subject: [PATCH 100/118] QPlatformWindow: don't call QScreen::virtualSiblings() ... when QT_NO_CURSOR is enabled. Then, result of this function is unneeded. Change-Id: I0e74e1aa5253de2608c4c18cb2c4b4e2e9f4c9e2 Reviewed-by: Friedemann Kleint --- src/gui/kernel/qplatformwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp index 769d30888b..1d444f94c9 100644 --- a/src/gui/kernel/qplatformwindow.cpp +++ b/src/gui/kernel/qplatformwindow.cpp @@ -552,8 +552,8 @@ static inline const QScreen *effectiveScreen(const QWindow *window) const QScreen *screen = window->screen(); if (!screen) return QGuiApplication::primaryScreen(); - const QList siblings = screen->virtualSiblings(); #ifndef QT_NO_CURSOR + const QList siblings = screen->virtualSiblings(); if (siblings.size() > 1) { const QPoint referencePoint = window->transientParent() ? window->transientParent()->geometry().center() : QCursor::pos(); for (const QScreen *sibling : siblings) { From bf44f002ca0caa789e1f6316598bf7cd7fe19ae5 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 23 Feb 2016 09:22:30 +0100 Subject: [PATCH 101/118] Blacklist tst_QTreeView::setSortingEnabledChild() on Windows. Task-number: QTBUG-51149 Change-Id: I7887aea5a6046353e235655665e53b5953f0854b Reviewed-by: Liang Qi --- tests/auto/widgets/itemviews/qtreeview/BLACKLIST | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/auto/widgets/itemviews/qtreeview/BLACKLIST diff --git a/tests/auto/widgets/itemviews/qtreeview/BLACKLIST b/tests/auto/widgets/itemviews/qtreeview/BLACKLIST new file mode 100644 index 0000000000..5eb80007c4 --- /dev/null +++ b/tests/auto/widgets/itemviews/qtreeview/BLACKLIST @@ -0,0 +1,2 @@ +[setSortingEnabledChild] +windows From 63b5f5cb98fe19af5bf20d4f581723cb91a46dcb Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 22 Feb 2016 16:17:10 +0100 Subject: [PATCH 102/118] Disable ligatures using existing mechanism in HB, not workaround This is a partial revert of fef629cd9191bb73f22c5efb6f943e6b672953c1. When doing the original fix, I didn't realize that there was a mechanism for disabling specific OpenType features in Harfbuzz. This commit reverts the hack to disable GSUB completely and disables the ligature features instead. Task-number: QTBUG-44393 Change-Id: I30f0080eb3897f37219df7f2d50843f3a4556e13 Reviewed-by: Konstantin Ritt --- src/gui/text/qharfbuzzng.cpp | 15 +-------------- src/gui/text/qharfbuzzng_p.h | 3 --- src/gui/text/qtextengine.cpp | 17 ++++++++++------- 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp index 6437465da8..b2edfc00a0 100644 --- a/src/gui/text/qharfbuzzng.cpp +++ b/src/gui/text/qharfbuzzng.cpp @@ -573,27 +573,17 @@ _hb_qt_font_get_glyph_from_name(hb_font_t * /*font*/, void * /*font_data*/, static hb_user_data_key_t _useDesignMetricsKey; -static hb_user_data_key_t _ignoreGSUB; void hb_qt_font_set_use_design_metrics(hb_font_t *font, uint value) { hb_font_set_user_data(font, &_useDesignMetricsKey, (void *)quintptr(value), NULL, true); } -void hb_qt_face_set_ignore_gsub(hb_face_t *face, uint value) -{ - hb_face_set_user_data(face, &_ignoreGSUB, (void *)quintptr(value), NULL, true); -} - uint hb_qt_font_get_use_design_metrics(hb_font_t *font) { return quintptr(hb_font_get_user_data(font, &_useDesignMetricsKey)); } -uint hb_qt_face_get_ignore_gsub(hb_face_t *face) -{ - return quintptr(hb_face_get_user_data(face, &_ignoreGSUB)); -} struct _hb_qt_font_funcs_t { _hb_qt_font_funcs_t() @@ -628,14 +618,11 @@ hb_font_funcs_t *hb_qt_get_font_funcs() static hb_blob_t * -_hb_qt_reference_table(hb_face_t *face, hb_tag_t tag, void *user_data) +_hb_qt_reference_table(hb_face_t * /*face*/, hb_tag_t tag, void *user_data) { QFontEngine::FaceData *data = static_cast(user_data); Q_ASSERT(data); - if (hb_qt_face_get_ignore_gsub(face) && tag == HB_TAG('G','S','U','B')) - return hb_blob_get_empty(); - qt_get_font_table_func_t get_font_table = data->get_font_table; Q_ASSERT(get_font_table); diff --git a/src/gui/text/qharfbuzzng_p.h b/src/gui/text/qharfbuzzng_p.h index 8beadbc72c..d5e11e6264 100644 --- a/src/gui/text/qharfbuzzng_p.h +++ b/src/gui/text/qharfbuzzng_p.h @@ -72,9 +72,6 @@ Q_GUI_EXPORT hb_font_t *hb_qt_font_get_for_engine(QFontEngine *fe); Q_GUI_EXPORT void hb_qt_font_set_use_design_metrics(hb_font_t *font, uint value); Q_GUI_EXPORT uint hb_qt_font_get_use_design_metrics(hb_font_t *font); -Q_GUI_EXPORT void hb_qt_face_set_ignore_gsub(hb_face_t *font, uint value); -Q_GUI_EXPORT uint hb_qt_face_get_ignore_gsub(hb_face_t *font); - QT_END_NAMESPACE #endif // QHARFBUZZNG_P_H diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 7dc8e8fadb..c545240c57 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1175,16 +1175,19 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, Q_ASSERT(hb_font); hb_qt_font_set_use_design_metrics(hb_font, option.useDesignMetrics() ? uint(QFontEngine::DesignMetrics) : 0); // ### + // Ligatures are incompatible with custom letter spacing, so when a letter spacing is set, + // we disable them for writing systems where they are purely cosmetic. bool scriptRequiresOpenType = ((script >= QChar::Script_Syriac && script <= QChar::Script_Sinhala) || script == QChar::Script_Khmer || script == QChar::Script_Nko); - hb_face_t *hb_face = hb_font_get_face(hb_font); - Q_ASSERT(hb_face); - hb_qt_face_set_ignore_gsub(hb_face, hasLetterSpacing && !scriptRequiresOpenType); - const hb_feature_t features[1] = { - { HB_TAG('k','e','r','n'), !!kerningEnabled, 0, uint(-1) } - }; - const int num_features = 1; + bool dontLigate = hasLetterSpacing && !scriptRequiresOpenType; + const hb_feature_t features[5] = { + { HB_TAG('k','e','r','n'), !!kerningEnabled, 0, uint(-1) }, + { HB_TAG('l','i','g','a'), !dontLigate, 0, uint(-1) }, + { HB_TAG('c','l','i','g'), !dontLigate, 0, uint(-1) }, + { HB_TAG('d','l','i','g'), !dontLigate, 0, uint(-1) }, + { HB_TAG('h','l','i','g'), !dontLigate, 0, uint(-1) } }; + const int num_features = dontLigate ? 5 : 1; const char *const *shaper_list = Q_NULLPTR; #if defined(Q_OS_DARWIN) From 7091be1b7999d93fe2126042161dcd1d8fd20026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Tue, 19 Jan 2016 22:32:52 +0100 Subject: [PATCH 103/118] xcb: Deliver mouse enter event to window when closing modal window When a modal window is closed and the mouse is not under the modal window - find a proper window and send a fake enter event. Added auto test for checking enter event on window when modal window is closed. Task-number: QTBUG-35109 Change-Id: I370b52d386503820ac9de21e6d05fd019ca456ec Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbwindow.cpp | 48 +++++ tests/auto/gui/kernel/qwindow/BLACKLIST | 2 + tests/auto/gui/kernel/qwindow/tst_qwindow.cpp | 193 ++++++++++++++++++ 3 files changed, 243 insertions(+) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 46b7b70f80..7eae2d92ab 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -50,6 +50,7 @@ #include "qxcbsystemtraytracker.h" #include +#include #include @@ -261,6 +262,26 @@ static inline XTextProperty* qstringToXTP(Display *dpy, const QString& s) } #endif // XCB_USE_XLIB +// TODO move this into a utility function in QWindow or QGuiApplication +static QWindow *childWindowAt(QWindow *win, const QPoint &p) +{ + foreach (QObject *obj, win->children()) { + if (obj->isWindowType()) { + QWindow *childWin = static_cast(obj); + if (childWin->isVisible()) { + if (QWindow *recurse = childWindowAt(childWin, p)) + return recurse; + } + } + } + if (!win->isTopLevel() + && !(win->flags() & Qt::WindowTransparentForInput) + && win->geometry().contains(win->parent()->mapFromGlobal(p))) { + return win; + } + return Q_NULLPTR; +} + static const char *wm_window_type_property_id = "_q_xcb_wm_window_type"; QXcbWindow::QXcbWindow(QWindow *window) @@ -855,6 +876,33 @@ void QXcbWindow::hide() connection()->setMouseGrabber(Q_NULLPTR); m_mapped = false; + + // Hiding a modal window doesn't send an enter event to its transient parent when the + // mouse is already over the parent window, so the enter event must be emulated. + if (window()->isModal()) { + // Get the cursor position at modal window screen + const QPoint nativePos = xcbScreen()->cursor()->pos(); + const QPoint cursorPos = QHighDpi::fromNativePixels(nativePos, xcbScreen()->screenForPosition(nativePos)->screen()); + + // Find the top level window at cursor position. + // Don't use QGuiApplication::topLevelAt(): search only the virtual siblings of this window's screen + QWindow *enterWindow = Q_NULLPTR; + foreach (QPlatformScreen *screen, xcbScreen()->virtualSiblings()) { + if (screen->geometry().contains(cursorPos)) { + const QPoint devicePosition = QHighDpi::toNativePixels(cursorPos, screen->screen()); + enterWindow = screen->topLevelAt(devicePosition); + break; + } + } + + if (enterWindow && enterWindow != window()) { + // Find the child window at cursor position, otherwise use the top level window + if (QWindow *childWindow = childWindowAt(enterWindow, cursorPos)) + enterWindow = childWindow; + const QPoint localPos = enterWindow->mapFromGlobal(cursorPos); + QWindowSystemInterface::handleEnterEvent(enterWindow, localPos, cursorPos); + } + } } static QWindow *tlWindow(QWindow *window) diff --git a/tests/auto/gui/kernel/qwindow/BLACKLIST b/tests/auto/gui/kernel/qwindow/BLACKLIST index 26cace1403..cfbd47745f 100644 --- a/tests/auto/gui/kernel/qwindow/BLACKLIST +++ b/tests/auto/gui/kernel/qwindow/BLACKLIST @@ -6,3 +6,5 @@ ubuntu-14.04 ubuntu-14.04 [modalWithChildWindow] ubuntu-14.04 +[modalWindowEnterEventOnHide_QTBUG35109] +ubuntu-14.04 diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp index a89f0da4d2..0cce5a072c 100644 --- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp +++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp @@ -92,6 +92,9 @@ private slots: void modalWithChildWindow(); void modalWindowModallity(); void modalWindowPosition(); +#ifndef QT_NO_CURSOR + void modalWindowEnterEventOnHide_QTBUG35109(); +#endif void windowsTransientChildren(); void requestUpdate(); void initTestCase(); @@ -706,10 +709,24 @@ public: } } } + bool event(QEvent *e) { + switch (e->type()) { + case QEvent::Enter: + ++enterEventCount; + break; + case QEvent::Leave: + ++leaveEventCount; + break; + default: + break; + } + return QWindow::event(e); + } void resetCounters() { mousePressedCount = mouseReleasedCount = mouseMovedCount = mouseDoubleClickedCount = 0; mouseSequenceSignature = QString(); touchPressedCount = touchReleasedCount = touchMovedCount = 0; + enterEventCount = leaveEventCount = 0; } InputTestWindow() { @@ -727,6 +744,7 @@ public: QPointF mousePressScreenPos, mouseMoveScreenPos, mousePressLocalPos; int touchPressedCount, touchReleasedCount, touchMovedCount; QEvent::Type touchEventType; + int enterEventCount, leaveEventCount; bool ignoreMouse, ignoreTouch; @@ -1732,6 +1750,181 @@ void tst_QWindow::modalWindowPosition() QCOMPARE(window.geometry(), origGeo); } +#ifndef QT_NO_CURSOR +void tst_QWindow::modalWindowEnterEventOnHide_QTBUG35109() +{ + if (QGuiApplication::platformName() == QLatin1String("cocoa")) + QSKIP("This test fails on OS X on CI"); + + const QPoint center = QGuiApplication::primaryScreen()->availableGeometry().center(); + + const int childOffset = 16; + const QPoint rootPos = center - QPoint(m_testWindowSize.width(), + m_testWindowSize.height())/2; + const QPoint modalPos = rootPos + QPoint(childOffset * 5, + childOffset * 5); + const QPoint cursorPos = rootPos - QPoint(80, 80); + + // Test whether tlw can receive the enter event + { + QCursor::setPos(cursorPos); + QCoreApplication::processEvents(); + + InputTestWindow root; + root.setTitle(__FUNCTION__); + root.setGeometry(QRect(rootPos, m_testWindowSize)); + root.show(); + QVERIFY(QTest::qWaitForWindowExposed(&root)); + root.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&root)); + + // Move the mouse over the root window, but not over the modal window. + QCursor::setPos(rootPos + QPoint(childOffset * 5 / 2, + childOffset * 5 / 2)); + + // Wait for the enter event. It must be delivered here, otherwise second + // compare can PASS because of this event even after "resetCounters()". + QTRY_COMPARE(root.enterEventCount, 1); + QTRY_COMPARE(root.leaveEventCount, 0); + + QWindow modal; + modal.setTitle(QLatin1String("Modal - ") + __FUNCTION__); + modal.setTransientParent(&root); + modal.resize(m_testWindowSize/2); + modal.setFramePosition(modalPos); + modal.setModality(Qt::ApplicationModal); + modal.show(); + QVERIFY(QTest::qWaitForWindowExposed(&modal)); + modal.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&modal)); + + QCoreApplication::processEvents(); + QTRY_COMPARE(root.leaveEventCount, 1); + + root.resetCounters(); + modal.close(); + + // Check for the enter event + QTRY_COMPARE(root.enterEventCount, 1); + } + + // Test whether child window can receive the enter event + { + QCursor::setPos(cursorPos); + QCoreApplication::processEvents(); + + QWindow root; + root.setTitle(__FUNCTION__); + root.setGeometry(QRect(rootPos, m_testWindowSize)); + + QWindow childLvl1; + childLvl1.setParent(&root); + childLvl1.setGeometry(childOffset, + childOffset, + m_testWindowSize.width() - childOffset, + m_testWindowSize.height() - childOffset); + + InputTestWindow childLvl2; + childLvl2.setParent(&childLvl1); + childLvl2.setGeometry(childOffset, + childOffset, + childLvl1.width() - childOffset, + childLvl1.height() - childOffset); + + root.show(); + childLvl1.show(); + childLvl2.show(); + + QVERIFY(QTest::qWaitForWindowExposed(&root)); + root.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&root)); + QVERIFY(childLvl1.isVisible()); + QVERIFY(childLvl2.isVisible()); + + // Move the mouse over the child window, but not over the modal window. + // Be sure that the value is almost left-top of second child window for + // checking proper position mapping. + QCursor::setPos(rootPos + QPoint(childOffset * 5 / 2, + childOffset * 5 / 2)); + + // Wait for the enter event. It must be delivered here, otherwise second + // compare can PASS because of this event even after "resetCounters()". + QTRY_COMPARE(childLvl2.enterEventCount, 1); + QTRY_COMPARE(childLvl2.leaveEventCount, 0); + + QWindow modal; + modal.setTitle(QLatin1String("Modal - ") + __FUNCTION__); + modal.setTransientParent(&root); + modal.resize(m_testWindowSize/2); + modal.setFramePosition(modalPos); + modal.setModality(Qt::ApplicationModal); + modal.show(); + QVERIFY(QTest::qWaitForWindowExposed(&modal)); + modal.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&modal)); + + QCoreApplication::processEvents(); + QTRY_COMPARE(childLvl2.leaveEventCount, 1); + + childLvl2.resetCounters(); + modal.close(); + + // Check for the enter event + QTRY_COMPARE(childLvl2.enterEventCount, 1); + } + + // Test whether tlw can receive the enter event if mouse is over the invisible child windnow + { + QCursor::setPos(cursorPos); + QCoreApplication::processEvents(); + + InputTestWindow root; + root.setTitle(__FUNCTION__); + root.setGeometry(QRect(rootPos, m_testWindowSize)); + + QWindow child; + child.setParent(&root); + child.setGeometry(QRect(QPoint(), m_testWindowSize)); + + root.show(); + + QVERIFY(QTest::qWaitForWindowExposed(&root)); + root.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&root)); + QVERIFY(!child.isVisible()); + + // Move the mouse over the child window, but not over the modal window. + QCursor::setPos(rootPos + QPoint(childOffset * 5 / 2, + childOffset * 5 / 2)); + + // Wait for the enter event. It must be delivered here, otherwise second + // compare can PASS because of this event even after "resetCounters()". + QTRY_COMPARE(root.enterEventCount, 1); + QTRY_COMPARE(root.leaveEventCount, 0); + + QWindow modal; + modal.setTitle(QLatin1String("Modal - ") + __FUNCTION__); + modal.setTransientParent(&root); + modal.resize(m_testWindowSize/2); + modal.setFramePosition(modalPos); + modal.setModality(Qt::ApplicationModal); + modal.show(); + QVERIFY(QTest::qWaitForWindowExposed(&modal)); + modal.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&modal)); + + QCoreApplication::processEvents(); + QTRY_COMPARE(root.leaveEventCount, 1); + + root.resetCounters(); + modal.close(); + + // Check for the enter event + QTRY_COMPARE(root.enterEventCount, 1); + } +} +#endif + class ColoredWindow : public QRasterWindow { public: explicit ColoredWindow(const QColor &color, QWindow *parent = 0) : QRasterWindow(parent), m_color(color) {} From 544bbcbcdabdd012cbcce484196053a0b9f37104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Tue, 9 Feb 2016 15:51:05 +0100 Subject: [PATCH 104/118] QtWidgets: Always deliver the wheel event to submenus When mouse events are delivered using XInput2 then the wheel event is missing on submenus, because XInput2 delivers the wheel event only to the root menu. Task-number: QTBUG-50996 Change-Id: I757c0b5e3aea4606d2e45dfc8180c263e02167ca Reviewed-by: Shawn Rutledge --- src/widgets/kernel/qwidgetwindow.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index b2a2ecc3b9..15c28d0913 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -747,13 +747,24 @@ void QWidgetWindow::handleWheelEvent(QWheelEvent *event) if (QApplicationPrivate::instance()->modalState() && !qt_try_modal(m_widget, event->type())) return; + QWidget *rootWidget = m_widget; + QPoint pos = event->pos(); + + // Use proper popup window for wheel event. Some QPA sends the wheel + // event to the root menu, so redirect it to the proper popup window. + QWidget *activePopupWidget = QApplication::activePopupWidget(); + if (activePopupWidget && activePopupWidget != m_widget) { + rootWidget = activePopupWidget; + pos = rootWidget->mapFromGlobal(event->globalPos()); + } + // which child should have it? - QWidget *widget = m_widget->childAt(event->pos()); + QWidget *widget = rootWidget->childAt(pos); if (!widget) - widget = m_widget; + widget = rootWidget; - QPoint mapped = widget->mapFrom(m_widget, event->pos()); + QPoint mapped = widget->mapFrom(rootWidget, pos); QWheelEvent translated(mapped, event->globalPos(), event->pixelDelta(), event->angleDelta(), event->delta(), event->orientation(), event->buttons(), event->modifiers(), event->phase(), event->source()); QGuiApplication::sendSpontaneousEvent(widget, &translated); From d8e65d5756c937fc3d9be3e5c30b31914a437393 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 22 Feb 2016 15:07:21 +0100 Subject: [PATCH 105/118] Fix font dialog with missing font family and pixel sizes Two related errors: When a non-existent font was set on the font dialog, the GTK native font dialog would just pick a default one. Also, if the font size was specified with pixel size, we would request -1 as the point size from Pango. The fix for both is to resolve the font before applying it to the font dialog, and set the actually resolved family, as well as point size. Note that if the point size is explicitly set, then we pass this to the font dialog, since the one returned by QFontInfo will always be calculated based on the (rounded) pixel size, so it will usually not match the request. This fixes tst_qfontdialog::setFont(). [ChangeLog][GTK2][Dialogs] Fixed requesting a font from font dialog with a non-existent family name and/or pixel size. Task-number: QTBUG-51148 Change-Id: Id9c783407778546b0cf3f9c3ab19f124e76c878e Reviewed-by: Shawn Rutledge Reviewed-by: J-P Nurmi --- src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp index 857f373759..f0a54ec92f 100644 --- a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp +++ b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp @@ -517,8 +517,8 @@ void QGtk2FontDialogHelper::hide() static QString qt_fontToString(const QFont &font) { PangoFontDescription *desc = pango_font_description_new(); - pango_font_description_set_size(desc, font.pointSizeF() * PANGO_SCALE); - pango_font_description_set_family(desc, font.family().toUtf8()); + pango_font_description_set_size(desc, (font.pointSizeF() > 0.0 ? font.pointSizeF() : QFontInfo(font).pointSizeF()) * PANGO_SCALE); + pango_font_description_set_family(desc, QFontInfo(font).family().toUtf8()); int weight = font.weight(); if (weight >= QFont::Black) From ff76300a5c9f209f625384f35ad0fdb0acebd799 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Fri, 19 Feb 2016 17:58:46 +0200 Subject: [PATCH 106/118] QRingBuffer::read(): remove unneeded byte array allocation QRingBuffer already works fine with empty list of arrays. Change-Id: I5cd388709686d2980efa3d5129c726e75c0b5c09 Reviewed-by: Oswald Buddenhagen --- src/corelib/tools/qringbuffer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/corelib/tools/qringbuffer.cpp b/src/corelib/tools/qringbuffer.cpp index 7e2d909dcd..db2004dfd9 100644 --- a/src/corelib/tools/qringbuffer.cpp +++ b/src/corelib/tools/qringbuffer.cpp @@ -276,7 +276,6 @@ QByteArray QRingBuffer::read() if (tailBuffer == 0) { qba.resize(tail); tail = 0; - buffers.append(QByteArray()); } else { --tailBuffer; } From c5687704e9b1e3f67c6a095c86368b8dc9809629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Fri, 13 Nov 2015 17:49:53 +0100 Subject: [PATCH 107/118] xcb: Remove unneeded null pointer checks Since a094af001795c9651b299d700a992150d1aba33a we don't need any null pointer checks for xcb screens. This reverts patch 7532fb4e61fc4102fd11022f57f7d8195414167b Change-Id: I8b90ed538aad4403650ef42aab6f39de5861d9ed Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbbackingstore.cpp | 13 ++----------- src/plugins/platforms/xcb/qxcbbackingstore.h | 1 - src/plugins/platforms/xcb/qxcbwindow.cpp | 4 ++-- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index d5a82a7509..e57b089878 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -326,12 +326,9 @@ QPaintDevice *QXcbBackingStore::paintDevice() void QXcbBackingStore::beginPaint(const QRegion ®ion) { - if (!m_image && !m_size.isEmpty()) - resize(m_size, QRegion()); - if (!m_image) return; - m_size = QSize(); + m_paintRegion = region; m_image->preparePaint(m_paintRegion); @@ -438,8 +435,7 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &) return; Q_XCB_NOOP(connection()); - - QXcbScreen *screen = window()->screen() ? static_cast(window()->screen()->handle()) : 0; + QXcbScreen *screen = static_cast(window()->screen()->handle()); QPlatformWindow *pw = window()->handle(); if (!pw) { window()->create(); @@ -448,11 +444,6 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &) QXcbWindow* win = static_cast(pw); delete m_image; - if (!screen) { - m_image = 0; - m_size = size; - return; - } m_image = new QXcbShmImage(screen, size, win->depth(), win->imageFormat()); // Slow path for bgr888 VNC: Create an additional image, paint into that and // swap R and B while copying to m_image after each paint. diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.h b/src/plugins/platforms/xcb/qxcbbackingstore.h index b3c0a74f25..1f5652d918 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.h +++ b/src/plugins/platforms/xcb/qxcbbackingstore.h @@ -77,7 +77,6 @@ private: QXcbShmImage *m_image; QRegion m_paintRegion; QImage m_rgbImage; - QSize m_size; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 939fd5e5b4..11202944bd 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -667,7 +667,7 @@ void QXcbWindow::setGeometry(const QRect &rect) const QRect wmGeometry = windowToWmGeometry(rect); - if (newScreen && newScreen != currentScreen) + if (newScreen != currentScreen) QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen()); if (qt_window_private(window())->positionAutomatic) { @@ -1660,7 +1660,7 @@ void QXcbWindow::requestActivateWindow() return; } - if (!m_mapped || !xcbScreen()) { + if (!m_mapped) { m_deferredActivation = true; return; } From 3ca2eea00d53ae1f75cead8dde763cb8e348d630 Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Thu, 18 Feb 2016 23:04:57 +0100 Subject: [PATCH 108/118] QSqlDriver:sqlStatement: respect generated flags for WHERE too Change-Id: I90034cd1a8dc0473c36d788c6737493a51641b02 Reviewed-by: Andy Shaw --- src/sql/kernel/qsqldriver.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/sql/kernel/qsqldriver.cpp b/src/sql/kernel/qsqldriver.cpp index d53331fb10..ac51941f43 100644 --- a/src/sql/kernel/qsqldriver.cpp +++ b/src/sql/kernel/qsqldriver.cpp @@ -466,6 +466,9 @@ QString QSqlDriver::stripDelimiters(const QString &identifier, IdentifierType ty with the values from \a rec. If \a preparedStatement is true, the string will contain placeholders instead of values. + The generated flag in each field of \a rec determines whether the + field is included in the generated statement. + This method can be used to manipulate tables without having to worry about database-dependent SQL dialects. For non-prepared statements, the values will be properly escaped. @@ -493,7 +496,9 @@ QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName, ? QString() : prepareIdentifier(tableName, QSqlDriver::TableName, this) + QLatin1Char('.'); for (int i = 0; i < rec.count(); ++i) { - s.append(QLatin1String(i? " AND " : "WHERE ")); + if (!rec.isGenerated(i)) + continue; + s.append(s.isEmpty() ? QLatin1String("WHERE ") : QLatin1String(" AND ")); s.append(tableNamePrefix); s.append(prepareIdentifier(rec.fieldName(i), QSqlDriver::FieldName, this)); if (rec.isNull(i)) From 68a85a03f96f5912151ff7412c508e52a27c9418 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 28 Feb 2015 15:19:44 +0100 Subject: [PATCH 109/118] QtWidgets: replace QStringLiteral with QLatin1String when appending It makes little sense to use QStringLiteral for strings which are immediately appended to, or which are appended to other strings, because no dynamic memory allocation is saved by doing so. But if the only advantage of QStringLiteral does not apply, all its disadvantages dominate, to wit: injection of calls to qstring dtor, non-sharability of data between C strings and QStringLiterals and among QStringLiterals, and doubled storage requirements. Fix by replacing QStringLiteral with QLatin1String. Saves 288B in text size on stripped optimized Linux AMD64 GCC 4.9 builds. Change-Id: Ie632f25883163f57991264b29e8753fe4c4f738e Reviewed-by: Friedemann Kleint Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/dialogs/qfiledialog.cpp | 2 +- src/widgets/kernel/qwidgetwindow.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 4d74292e8f..50667e2a91 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -1527,7 +1527,7 @@ static QString nameFilterForMime(const QString &mimeType) return QFileDialog::tr("All files (*)"); } else { const QString patterns = mime.globPatterns().join(QLatin1Char(' ')); - return mime.comment() + QStringLiteral(" (") + patterns + QLatin1Char(')'); + return mime.comment() + QLatin1String(" (") + patterns + QLatin1Char(')'); } } return QString(); diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 90473c6642..6a3785ea03 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -1001,8 +1001,8 @@ void QWidgetWindow::updateObjectName() { QString name = m_widget->objectName(); if (name.isEmpty()) - name = QString::fromUtf8(m_widget->metaObject()->className()) + QStringLiteral("Class"); - name += QStringLiteral("Window"); + name = QString::fromUtf8(m_widget->metaObject()->className()) + QLatin1String("Class"); + name += QLatin1String("Window"); setObjectName(name); } From 215bda50f959673f076fe76cf1f95a2a5f759b2c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 28 Feb 2015 15:18:39 +0100 Subject: [PATCH 110/118] QtGui: replace QStringLiteral with QLatin1String when appending It makes little sense to use QStringLiteral for strings which are immediately appended to, or which are appended to other strings, because no dynamic memory allocation is saved by doing so. But if the only advantage of QStringLiteral does not apply, all its disadvantages dominate, to wit: injection of calls to qstring dtor, non-sharability of data between C strings and QStringLiterals and among QStringLiterals, and doubled storage requirements. Fix by replacing QStringLiteral with QLatin1String. Saves 104B in text size on stripped optimized Linux AMD64 GCC 4.9 builds. Change-Id: I36b6a9bb1963b69361cc3a3db0971e1db92f0080 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/gui/kernel/qplatformdialoghelper.cpp | 4 ++-- src/gui/util/qvalidator.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp index f2a1d20d54..fe4d167078 100644 --- a/src/gui/kernel/qplatformdialoghelper.cpp +++ b/src/gui/kernel/qplatformdialoghelper.cpp @@ -258,7 +258,7 @@ void QColorDialogStaticData::readSettings() #ifndef QT_NO_SETTINGS const QSettings settings(QSettings::UserScope, QStringLiteral("QtProject")); for (int i = 0; i < int(CustomColorCount); ++i) { - const QVariant v = settings.value(QStringLiteral("Qt/customColors/") + QString::number(i)); + const QVariant v = settings.value(QLatin1String("Qt/customColors/") + QString::number(i)); if (v.isValid()) customRgb[i] = v.toUInt(); } @@ -271,7 +271,7 @@ void QColorDialogStaticData::writeSettings() const if (!customSet) { QSettings settings(QSettings::UserScope, QStringLiteral("QtProject")); for (int i = 0; i < int(CustomColorCount); ++i) - settings.setValue(QStringLiteral("Qt/customColors/") + QString::number(i), customRgb[i]); + settings.setValue(QLatin1String("Qt/customColors/") + QString::number(i), customRgb[i]); } #endif } diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp index 430de3aef8..90c6e7a7b8 100644 --- a/src/gui/util/qvalidator.cpp +++ b/src/gui/util/qvalidator.cpp @@ -1066,7 +1066,7 @@ void QRegularExpressionValidatorPrivate::setRegularExpression(const QRegularExpr if (origRe != re) { usedRe = origRe = re; // copies also the pattern options - usedRe.setPattern(QStringLiteral("\\A(?:") + re.pattern() + QStringLiteral(")\\z")); + usedRe.setPattern(QLatin1String("\\A(?:") + re.pattern() + QLatin1String(")\\z")); emit q->regularExpressionChanged(re); emit q->changed(); } From 71b106ab436f75d3467a71b1b3739ce570b62522 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 23 Feb 2016 21:53:08 +0100 Subject: [PATCH 111/118] QMimeTypeParser: use QStringRef more Keep the return values of QXmlStream*::value() around as QStringRefs for as long as possible. Avoids conversions to QString, among other things, for: - comparison to another string - conversion to int - conversion to UTF-8 or Latin-1 byte arrays Add a pair of Q_UNLIKELY as a drive-by. Saves ~900b in text size on optimized GCC 5.3 Linux AMD64 builds. Change-Id: I17d440a11aeb8675979483f89e66d0a088ccc605 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/mimetypes/qmimemagicrule.cpp | 8 ++++---- src/corelib/mimetypes/qmimetypeparser.cpp | 20 ++++++++++---------- src/corelib/mimetypes/qmimetypeparser_p.h | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/corelib/mimetypes/qmimemagicrule.cpp b/src/corelib/mimetypes/qmimemagicrule.cpp index 09473caa78..06628fa323 100644 --- a/src/corelib/mimetypes/qmimemagicrule.cpp +++ b/src/corelib/mimetypes/qmimemagicrule.cpp @@ -238,10 +238,10 @@ QMimeMagicRule::QMimeMagicRule(const QString &type, // Parse for offset as "1" or "1:10" const int colonIndex = offsets.indexOf(QLatin1Char(':')); - const QString startPosStr = colonIndex == -1 ? offsets : offsets.mid(0, colonIndex); - const QString endPosStr = colonIndex == -1 ? offsets : offsets.mid(colonIndex + 1); - if (!QMimeTypeParserBase::parseNumber(startPosStr, &m_startPos, errorString) || - !QMimeTypeParserBase::parseNumber(endPosStr, &m_endPos, errorString)) { + const QStringRef startPosStr = offsets.midRef(0, colonIndex); // \ These decay to returning 'offsets' + const QStringRef endPosStr = offsets.midRef(colonIndex + 1);// / unchanged when colonIndex == -1 + if (Q_UNLIKELY(!QMimeTypeParserBase::parseNumber(startPosStr, &m_startPos, errorString)) || + Q_UNLIKELY(!QMimeTypeParserBase::parseNumber(endPosStr, &m_endPos, errorString))) { m_type = Invalid; return; } diff --git a/src/corelib/mimetypes/qmimetypeparser.cpp b/src/corelib/mimetypes/qmimetypeparser.cpp index 4e348b08ac..b0d599fb0e 100644 --- a/src/corelib/mimetypes/qmimetypeparser.cpp +++ b/src/corelib/mimetypes/qmimetypeparser.cpp @@ -160,12 +160,12 @@ QMimeTypeParserBase::ParseState QMimeTypeParserBase::nextState(ParseState curren } // Parse int number from an (attribute) string -bool QMimeTypeParserBase::parseNumber(const QString &n, int *target, QString *errorMessage) +bool QMimeTypeParserBase::parseNumber(const QStringRef &n, int *target, QString *errorMessage) { bool ok; *target = n.toInt(&ok); if (!ok) { - *errorMessage = QString::fromLatin1("Not a number '%1'.").arg(n); + *errorMessage = QLatin1String("Not a number '") + n + QLatin1String("'."); return false; } return true; @@ -174,11 +174,11 @@ bool QMimeTypeParserBase::parseNumber(const QString &n, int *target, QString *er #ifndef QT_NO_XMLSTREAMREADER static QMimeMagicRule *createMagicMatchRule(const QXmlStreamAttributes &atts, QString *errorMessage) { - const QString type = atts.value(QLatin1String(matchTypeAttributeC)).toString(); - const QString value = atts.value(QLatin1String(matchValueAttributeC)).toString(); - const QString offsets = atts.value(QLatin1String(matchOffsetAttributeC)).toString(); - const QString mask = atts.value(QLatin1String(matchMaskAttributeC)).toString(); - return new QMimeMagicRule(type, value.toUtf8(), offsets, mask.toLatin1(), errorMessage); + const QStringRef type = atts.value(QLatin1String(matchTypeAttributeC)); + const QStringRef value = atts.value(QLatin1String(matchValueAttributeC)); + const QStringRef offsets = atts.value(QLatin1String(matchOffsetAttributeC)); + const QStringRef mask = atts.value(QLatin1String(matchMaskAttributeC)); + return new QMimeMagicRule(type.toString(), value.toUtf8(), offsets.toString(), mask.toLatin1(), errorMessage); } #endif @@ -219,8 +219,8 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString break; case ParseGlobPattern: { const QString pattern = atts.value(QLatin1String(patternAttributeC)).toString(); - unsigned weight = atts.value(QLatin1String(weightAttributeC)).toString().toInt(); - const bool caseSensitive = atts.value(QLatin1String(caseSensitiveAttributeC)).toString() == QLatin1String("true"); + unsigned weight = atts.value(QLatin1String(weightAttributeC)).toInt(); + const bool caseSensitive = atts.value(QLatin1String(caseSensitiveAttributeC)) == QLatin1String("true"); if (weight == 0) weight = QMimeGlobPattern::DefaultWeight; @@ -255,7 +255,7 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString break; case ParseMagic: { priority = 50; - const QString priorityS = atts.value(QLatin1String(priorityAttributeC)).toString(); + const QStringRef priorityS = atts.value(QLatin1String(priorityAttributeC)); if (!priorityS.isEmpty()) { if (!parseNumber(priorityS, &priority, errorMessage)) return false; diff --git a/src/corelib/mimetypes/qmimetypeparser_p.h b/src/corelib/mimetypes/qmimetypeparser_p.h index cc11b70e71..a502439419 100644 --- a/src/corelib/mimetypes/qmimetypeparser_p.h +++ b/src/corelib/mimetypes/qmimetypeparser_p.h @@ -72,7 +72,7 @@ public: bool parse(QIODevice *dev, const QString &fileName, QString *errorMessage); - static bool parseNumber(const QString &n, int *target, QString *errorMessage); + static bool parseNumber(const QStringRef &n, int *target, QString *errorMessage); protected: virtual bool process(const QMimeType &t, QString *errorMessage) = 0; From a4dee8e274f00a65bdd3ad706db6c39d4a82759d Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 23 Feb 2016 22:01:52 +0100 Subject: [PATCH 112/118] QMimeTypeParser: use QStringBuilder more Replace QString::arg() with QStringBuilder, use QStringLiteral where appropriate, and remove it where it isn't (e.g. in QStringBuilder expressions). Saves ~750b in text size on optimized GCC 5.3 Linux AMD64 builds. Change-Id: I2471c849db79f477677213f9a155053248800590 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/mimetypes/qmimemagicrule.cpp | 13 +++++-------- src/corelib/mimetypes/qmimetypeparser.cpp | 5 ++--- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/corelib/mimetypes/qmimemagicrule.cpp b/src/corelib/mimetypes/qmimemagicrule.cpp index 06628fa323..528dca3ff5 100644 --- a/src/corelib/mimetypes/qmimemagicrule.cpp +++ b/src/corelib/mimetypes/qmimemagicrule.cpp @@ -234,7 +234,7 @@ QMimeMagicRule::QMimeMagicRule(const QString &type, m_matchFunction(nullptr) { if (m_type == Invalid) - *errorString = QStringLiteral("Type %s is not supported").arg(type); + *errorString = QLatin1String("Type ") + type + QLatin1String(" is not supported"); // Parse for offset as "1" or "1:10" const int colonIndex = offsets.indexOf(QLatin1Char(':')); @@ -249,7 +249,7 @@ QMimeMagicRule::QMimeMagicRule(const QString &type, if (m_value.isEmpty()) { m_type = Invalid; if (errorString) - *errorString = QLatin1String("Invalid empty magic rule value"); + *errorString = QStringLiteral("Invalid empty magic rule value"); return; } @@ -259,8 +259,7 @@ QMimeMagicRule::QMimeMagicRule(const QString &type, if (!ok) { m_type = Invalid; if (errorString) - *errorString = QString::fromLatin1("Invalid magic rule value \"%1\"").arg( - QString::fromLatin1(m_value)); + *errorString = QLatin1String("Invalid magic rule value \"") + QLatin1String(m_value) + QLatin1Char('"'); return; } m_numberMask = !m_mask.isEmpty() ? m_mask.toUInt(&ok, 0) : 0; // autodetect base @@ -274,8 +273,7 @@ QMimeMagicRule::QMimeMagicRule(const QString &type, if (m_mask.size() < 4 || !m_mask.startsWith("0x")) { m_type = Invalid; if (errorString) - *errorString = QString::fromLatin1("Invalid magic rule mask \"%1\"").arg( - QString::fromLatin1(m_mask)); + *errorString = QLatin1String("Invalid magic rule mask \"") + QLatin1String(m_mask) + QLatin1Char('"'); return; } const QByteArray &tempMask = QByteArray::fromHex(QByteArray::fromRawData( @@ -283,8 +281,7 @@ QMimeMagicRule::QMimeMagicRule(const QString &type, if (tempMask.size() != m_pattern.size()) { m_type = Invalid; if (errorString) - *errorString = QString::fromLatin1("Invalid magic rule mask size \"%1\"").arg( - QString::fromLatin1(m_mask)); + *errorString = QLatin1String("Invalid magic rule mask size \"") + QLatin1String(m_mask) + QLatin1Char('"'); return; } m_mask = tempMask; diff --git a/src/corelib/mimetypes/qmimetypeparser.cpp b/src/corelib/mimetypes/qmimetypeparser.cpp index b0d599fb0e..0751c1feed 100644 --- a/src/corelib/mimetypes/qmimetypeparser.cpp +++ b/src/corelib/mimetypes/qmimetypeparser.cpp @@ -205,7 +205,7 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString case ParseMimeType: { // start parsing a MIME type name const QString name = atts.value(QLatin1String(mimeTypeAttributeC)).toString(); if (name.isEmpty()) { - reader.raiseError(QString::fromLatin1("Missing '%1'-attribute").arg(QString::fromLatin1(mimeTypeAttributeC))); + reader.raiseError(QStringLiteral("Missing 'type'-attribute")); } else { data.name = name; } @@ -282,8 +282,7 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString break; } case ParseError: - reader.raiseError(QString::fromLatin1("Unexpected element <%1>"). - arg(reader.name().toString())); + reader.raiseError(QLatin1String("Unexpected element <") + reader.name() + QLatin1Char('>')); break; default: break; From aca859cbc4c599e0c996dd2f3df148d59e3f590a Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 23 Feb 2016 22:12:20 +0100 Subject: [PATCH 113/118] QMimeTypeParser: don't use the heap to create QMimeMagicRules The function createMagicMatchRule() returned a heap-allocated QMimeMagicRule, and the caller code did not check the return value for nullptr, but copied the rule into a container before deleting the original again. Fix by returning by-value instead. Every C++ compiler will use RVO for this. On top, add an optimistic std::move() when inserting the rule into the container (currently QList, so no rvalue-push_back, yet). While touching the return value, also remove an unholy out-parameter with just local effects by returning a Result struct instead. The rest of the code remains full of out- parameters, of course. Add one Q_UNLIKELY and two qUtf16Printable() as drive-bys. Saves ~300b in text size on optimized GCC 5.3 Linux AMD64 builds. Change-Id: I4374ab41f38502cd5c64ac37d106ca4bc6e00327 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/mimetypes/qmimetypeparser.cpp | 26 ++++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/corelib/mimetypes/qmimetypeparser.cpp b/src/corelib/mimetypes/qmimetypeparser.cpp index 0751c1feed..cdb50b25e7 100644 --- a/src/corelib/mimetypes/qmimetypeparser.cpp +++ b/src/corelib/mimetypes/qmimetypeparser.cpp @@ -172,13 +172,24 @@ bool QMimeTypeParserBase::parseNumber(const QStringRef &n, int *target, QString } #ifndef QT_NO_XMLSTREAMREADER -static QMimeMagicRule *createMagicMatchRule(const QXmlStreamAttributes &atts, QString *errorMessage) +struct CreateMagicMatchRuleResult { + QString errorMessage; // must be first + QMimeMagicRule rule; + + CreateMagicMatchRuleResult(const QStringRef &type, const QStringRef &value, const QStringRef &offsets, const QStringRef &mask) + : errorMessage(), rule(type.toString(), value.toUtf8(), offsets.toString(), mask.toLatin1(), &errorMessage) + { + + } +}; + +static CreateMagicMatchRuleResult createMagicMatchRule(const QXmlStreamAttributes &atts) { const QStringRef type = atts.value(QLatin1String(matchTypeAttributeC)); const QStringRef value = atts.value(QLatin1String(matchValueAttributeC)); const QStringRef offsets = atts.value(QLatin1String(matchOffsetAttributeC)); const QStringRef mask = atts.value(QLatin1String(matchMaskAttributeC)); - return new QMimeMagicRule(type.toString(), value.toUtf8(), offsets.toString(), mask.toLatin1(), errorMessage); + return CreateMagicMatchRuleResult(type, value, offsets, mask); } #endif @@ -266,19 +277,18 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString } break; case ParseMagicMatchRule: { - QString magicErrorMessage; - QMimeMagicRule *rule = createMagicMatchRule(atts, &magicErrorMessage); - if (!rule->isValid()) - qWarning("QMimeDatabase: Error parsing %s\n%s", qPrintable(fileName), qPrintable(magicErrorMessage)); + auto result = createMagicMatchRule(atts); + if (Q_UNLIKELY(!result.rule.isValid())) + qWarning("QMimeDatabase: Error parsing %ls\n%ls", + qUtf16Printable(fileName), qUtf16Printable(result.errorMessage)); QList *ruleList; if (currentRules.isEmpty()) ruleList = &rules; else // nest this rule into the proper parent ruleList = ¤tRules.top()->m_subMatches; - ruleList->append(*rule); + ruleList->append(std::move(result.rule)); //qDebug() << " MATCH added. Stack size was" << currentRules.size(); currentRules.push(&ruleList->last()); - delete rule; break; } case ParseError: From c05f2985eb90c7e18dee99676f0a5da3239e30b9 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 23 Feb 2016 22:37:17 +0100 Subject: [PATCH 114/118] QMimeTypeParser: scope a variable better The variable being a QVector, this means replacing default construction followed by one move-assignment per loop iteration with a StartElement state with RVO-catching a return value. Saves ~320b in text size on optimized GCC 5.3 Linux AMD64 builds. Change-Id: I618d31ad0816f9ad1a89a6b2e39481258f1e0878 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/mimetypes/qmimetypeparser.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/corelib/mimetypes/qmimetypeparser.cpp b/src/corelib/mimetypes/qmimetypeparser.cpp index cdb50b25e7..9ed345d37e 100644 --- a/src/corelib/mimetypes/qmimetypeparser.cpp +++ b/src/corelib/mimetypes/qmimetypeparser.cpp @@ -206,12 +206,11 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString QList rules; // toplevel rules QXmlStreamReader reader(dev); ParseState ps = ParseBeginning; - QXmlStreamAttributes atts; while (!reader.atEnd()) { switch (reader.readNext()) { - case QXmlStreamReader::StartElement: + case QXmlStreamReader::StartElement: { ps = nextState(ps, reader.name()); - atts = reader.attributes(); + const QXmlStreamAttributes atts = reader.attributes(); switch (ps) { case ParseMimeType: { // start parsing a MIME type name const QString name = atts.value(QLatin1String(mimeTypeAttributeC)).toString(); @@ -297,6 +296,7 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString default: break; } + } break; // continue switch QXmlStreamReader::Token... case QXmlStreamReader::EndElement: // Finished element From 3376e67abe3a1ae5b3293b9c71b51e477c026b83 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Mon, 15 Feb 2016 19:19:58 +0200 Subject: [PATCH 115/118] Perfect (almost) Qt on Android splash screen. There is no need to show the splash image immediately when the application starts, because it will be removed shortly in QtActivityDelegate.java, therefore show the splash in QtActivityDelegate.java. This patch also adds a new option to AndroidManifest.xml which keeps the splash screen visible until user to decides to hide it, by using the QtAndroid::hideSplashScreen() function. Change-Id: I8a29a5a757d626c4c9d6a2748a60ca3091ebf82d Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../qt5/android/QtActivityDelegate.java | 47 ++++++++++++------- .../org/qtproject/qt5/android/QtNative.java | 11 +++++ .../android/bindings/QtActivityLoader.java | 9 ---- src/android/templates/AndroidManifest.xml | 1 + src/corelib/kernel/qjnihelpers.cpp | 8 +++- src/corelib/kernel/qjnihelpers_p.h | 2 + 6 files changed, 52 insertions(+), 26 deletions(-) diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index 66600512a0..61a824e749 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -48,6 +48,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; import android.graphics.Rect; import android.net.LocalServerSocket; import android.net.LocalSocket; @@ -74,6 +75,7 @@ import android.view.ViewGroup; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.view.ViewTreeObserver; +import android.widget.ImageView; import android.widget.PopupMenu; import java.io.BufferedReader; @@ -127,6 +129,8 @@ public class QtActivityDelegate private HashMap m_surfaces = null; private HashMap m_nativeViews = null; private QtLayout m_layout = null; + private ImageView m_splashScreen = null; + private boolean m_splashScreenSticky = false; private QtEditText m_editText = null; private InputMethodManager m_imm = null; private boolean m_quitApp = true; @@ -873,6 +877,22 @@ public class QtActivityDelegate }; } m_layout = new QtLayout(m_activity, startApplication); + + try { + ActivityInfo info = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(), PackageManager.GET_META_DATA); + if (info.metaData.containsKey("android.app.splash_screen_drawable")) { + m_splashScreenSticky = info.metaData.containsKey("android.app.splash_screen_sticky") && info.metaData.getBoolean("android.app.splash_screen_sticky"); + int id = info.metaData.getInt("android.app.splash_screen_drawable"); + m_splashScreen = new ImageView(m_activity); + m_splashScreen.setImageDrawable(m_activity.getResources().getDrawable(id)); + m_splashScreen.setScaleType(ImageView.ScaleType.FIT_XY); + m_splashScreen.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + m_layout.addView(m_splashScreen); + } + } catch (Exception e) { + e.printStackTrace(); + } + m_editText = new QtEditText(m_activity, this); m_imm = (InputMethodManager)m_activity.getSystemService(Context.INPUT_METHOD_SERVICE); m_surfaces = new HashMap(); @@ -914,6 +934,15 @@ public class QtActivityDelegate }); } + public void hideSplashScreen() + { + if (m_splashScreen == null) + return; + m_layout.removeView(m_splashScreen); + m_splashScreen = null; + } + + public void initializeAccessibility() { new QtAccessibilityDelegate(m_activity, m_layout, this); @@ -937,22 +966,6 @@ public class QtActivityDelegate e.printStackTrace(); } - // if splash screen is defined, then show it - // Note: QtActivity handles settting the splash screen - // in onCreate, change that too if you are changing - // how the splash screen should be displayed - try { - if (m_surfaces.size() == 0) { - ActivityInfo info = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(), PackageManager.GET_META_DATA); - if (info.metaData.containsKey("android.app.splash_screen_drawable")) - m_activity.getWindow().setBackgroundDrawableResource(info.metaData.getInt("android.app.splash_screen_drawable")); - else - m_activity.getWindow().setBackgroundDrawable(new ColorDrawable(0xff000000)); - } - } catch (Exception e) { - e.printStackTrace(); - } - int rotation = m_activity.getWindowManager().getDefaultDisplay().getRotation(); if (rotation != m_currentRotation) { QtNative.handleOrientationChanged(rotation, m_nativeOrientation); @@ -1274,6 +1287,8 @@ public class QtActivityDelegate m_layout.addView(surface, surfaceCount); m_surfaces.put(id, surface); + if (!m_splashScreenSticky) + hideSplashScreen(); } public void setSurfaceGeometry(int id, int x, int y, int w, int h) { diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java index 5d4f6e791a..48510b3fdf 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -728,6 +728,17 @@ public class QtNative }); } + private static void hideSplashScreen() + { + runAction(new Runnable() { + @Override + public void run() { + if (m_activityDelegate != null) + m_activityDelegate.hideSplashScreen(); + } + }); + } + // screen methods public static native void setDisplayMetrics(int screenWidthPixels, int screenHeightPixels, diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java index 836a7677b3..92cea65e4b 100644 --- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java +++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java @@ -166,15 +166,6 @@ public class QtActivityLoader extends QtLoader { + "/\tQT_ANDROID_THEME_DISPLAY_DPI=" + m_displayDensity + "\t"; if (null == m_activity.getLastNonConfigurationInstance()) { - // if splash screen is defined, then show it - // Note: QtActivityDelegate handles updating the splash screen - // in onConfigurationChanged, change that too if you are changing - // how the splash screen should be displayed - if (m_contextInfo.metaData.containsKey("android.app.splash_screen_drawable")) - m_activity.getWindow().setBackgroundDrawableResource(m_contextInfo.metaData.getInt("android.app.splash_screen_drawable")); - else - m_activity.getWindow().setBackgroundDrawable(new ColorDrawable(0xff000000)); - if (m_contextInfo.metaData.containsKey("android.app.background_running") && m_contextInfo.metaData.getBoolean("android.app.background_running")) { ENVIRONMENT_VARIABLES += "QT_BLOCK_EVENT_LOOPS_WHEN_SUSPENDED=0\t"; diff --git a/src/android/templates/AndroidManifest.xml b/src/android/templates/AndroidManifest.xml index 02fd0ce23b..22c3ea7578 100644 --- a/src/android/templates/AndroidManifest.xml +++ b/src/android/templates/AndroidManifest.xml @@ -38,6 +38,7 @@ + diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp index f576ed0d1c..76f530ab9c 100644 --- a/src/corelib/kernel/qjnihelpers.cpp +++ b/src/corelib/kernel/qjnihelpers.cpp @@ -56,6 +56,7 @@ static jobject g_jClassLoader = Q_NULLPTR; static jint g_androidSdkVersion = 0; static jclass g_jNativeClass = Q_NULLPTR; static jmethodID g_runPendingCppRunnablesMethodID = Q_NULLPTR; +static jmethodID g_hideSplashScreenMethodID = Q_NULLPTR; Q_GLOBAL_STATIC(std::deque, g_pendingRunnables); Q_GLOBAL_STATIC(QMutex, g_pendingRunnablesMutex); @@ -338,7 +339,7 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env) g_runPendingCppRunnablesMethodID = env->GetStaticMethodID(jQtNative, "runPendingCppRunnablesOnUiThread", "()V"); - + g_hideSplashScreenMethodID = env->GetStaticMethodID(jQtNative, "hideSplashScreen", "()V"); g_jNativeClass = static_cast(env->NewGlobalRef(jQtNative)); env->DeleteLocalRef(jQtNative); @@ -424,4 +425,9 @@ void QtAndroidPrivate::unregisterKeyEventListener(QtAndroidPrivate::KeyEventList g_keyEventListeners()->listeners.removeOne(listener); } +void QtAndroidPrivate::hideSplashScreen(JNIEnv *env) +{ + env->CallStaticVoidMethod(g_jNativeClass, g_hideSplashScreenMethodID); +} + QT_END_NAMESPACE diff --git a/src/corelib/kernel/qjnihelpers_p.h b/src/corelib/kernel/qjnihelpers_p.h index 34bdbf6c80..78ad08a09e 100644 --- a/src/corelib/kernel/qjnihelpers_p.h +++ b/src/corelib/kernel/qjnihelpers_p.h @@ -127,6 +127,8 @@ namespace QtAndroidPrivate Q_CORE_EXPORT void registerKeyEventListener(KeyEventListener *listener); Q_CORE_EXPORT void unregisterKeyEventListener(KeyEventListener *listener); + + Q_CORE_EXPORT void hideSplashScreen(JNIEnv *env); } QT_END_NAMESPACE From 8b5651eb41954cbcbcb3ddd66179711dac0bc1df Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 24 Feb 2016 18:38:17 +0100 Subject: [PATCH 116/118] QtNetwork: don't use Boyer-Moore for single-character needles Using Boyer-Moore for single-character search strings makes no sense since there can be no skipping beyond the normal sequential search anyway. So, port to QByteArray::indexOf(char). Change-Id: I848e2ceea5ceafd0ebae402798b410f682348a75 Reviewed-by: Richard J. Moore --- src/network/access/qhttpnetworkreply.cpp | 8 ++------ src/network/ssl/qsslkey_p.cpp | 7 ++----- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index eda9dac745..f4510c3498 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -40,8 +40,6 @@ #include "qhttpnetworkreply_p.h" #include "qhttpnetworkconnection_p.h" -#include - #ifndef QT_NO_HTTP #ifndef QT_NO_SSL @@ -611,11 +609,9 @@ void QHttpNetworkReplyPrivate::parseHeader(const QByteArray &header) { // see rfc2616, sec 4 for information about HTTP/1.1 headers. // allows relaxed parsing here, accepts both CRLF & LF line endings - const QByteArrayMatcher lf("\n"); - const QByteArrayMatcher colon(":"); int i = 0; while (i < header.count()) { - int j = colon.indexIn(header, i); // field-name + int j = header.indexOf(':', i); // field-name if (j == -1) break; const QByteArray field = header.mid(i, j - i).trimmed(); @@ -623,7 +619,7 @@ void QHttpNetworkReplyPrivate::parseHeader(const QByteArray &header) // any number of LWS is allowed before and after the value QByteArray value; do { - i = lf.indexIn(header, j); + i = header.indexOf('\n', j); if (i == -1) break; if (!value.isEmpty()) diff --git a/src/network/ssl/qsslkey_p.cpp b/src/network/ssl/qsslkey_p.cpp index f26b178d0e..34f664093c 100644 --- a/src/network/ssl/qsslkey_p.cpp +++ b/src/network/ssl/qsslkey_p.cpp @@ -61,7 +61,6 @@ #include #include -#include #include #ifndef QT_NO_DEBUG_STREAM #include @@ -191,11 +190,9 @@ QByteArray QSslKeyPrivate::derFromPem(const QByteArray &pem, QMap Date: Sat, 28 Feb 2015 15:18:11 +0100 Subject: [PATCH 117/118] QtCore: replace QStringLiteral with QLatin1String when appending It makes little sense to use QStringLiteral for strings which are immediately appended to, or which are appended to other strings, because no dynamic memory allocation is saved by doing so. But if the only advantage of QStringLiteral does not apply, all its disadvantages dominate, to wit: injection of calls to qstring dtor, non-sharability of data between C strings and QStringLiterals and among QStringLiterals, and doubled storage requirements. Fix by replacing QStringLiteral with QLatin1String. Saves 1156B in text size on stripped optimized Linux AMD64 GCC 4.9 builds. Change-Id: If805e431f570ec1d2ac62c548f516f1b17390c3a Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/io/qfile.cpp | 2 +- src/corelib/io/qlockfile.cpp | 2 +- src/corelib/io/qurl.cpp | 2 +- src/corelib/tools/qcommandlineparser.cpp | 2 +- src/corelib/tools/qtimezoneprivate_win.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index ccacb6ed20..9b1bd3a411 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -581,7 +581,7 @@ QFile::rename(const QString &newName) #ifdef Q_OS_LINUX // rename() on Linux simply does nothing when renaming "foo" to "Foo" on a case-insensitive // FS, such as FAT32. Move the file away and rename in 2 steps to work around. - QTemporaryFile tempFile(d->fileName + QStringLiteral(".XXXXXX")); + QTemporaryFile tempFile(d->fileName + QLatin1String(".XXXXXX")); tempFile.setAutoRemove(false); if (!tempFile.open(QIODevice::ReadWrite)) { d->setError(QFile::RenameError, tempFile.errorString()); diff --git a/src/corelib/io/qlockfile.cpp b/src/corelib/io/qlockfile.cpp index 88a96125bc..7e39dc56fb 100644 --- a/src/corelib/io/qlockfile.cpp +++ b/src/corelib/io/qlockfile.cpp @@ -227,7 +227,7 @@ bool QLockFile::tryLock(int timeout) if (!d->isLocked && d->isApparentlyStale()) { // Stale lock from another thread/process // Ensure two processes don't remove it at the same time - QLockFile rmlock(d->fileName + QStringLiteral(".rmlock")); + QLockFile rmlock(d->fileName + QLatin1String(".rmlock")); if (rmlock.tryLock()) { if (d->isApparentlyStale() && d->removeStaleLock()) continue; diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 7b1fee31b4..18eaea7e21 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -4271,7 +4271,7 @@ QUrl QUrl::fromUserInput(const QString &userInput) return QUrl::fromLocalFile(trimmedString); QUrl url = QUrl(trimmedString, QUrl::TolerantMode); - QUrl urlPrepended = QUrl(QStringLiteral("http://") + trimmedString, QUrl::TolerantMode); + QUrl urlPrepended = QUrl(QLatin1String("http://") + trimmedString, QUrl::TolerantMode); // Check the most common case of a valid url with a scheme // We check if the port would be valid by adding the scheme to handle the case host:port diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp index a9d3c7f5d8..6587d900d2 100644 --- a/src/corelib/tools/qcommandlineparser.cpp +++ b/src/corelib/tools/qcommandlineparser.cpp @@ -1029,7 +1029,7 @@ QString QCommandLineParser::helpText() const static QString wrapText(const QString &names, int longestOptionNameString, const QString &description) { const QLatin1Char nl('\n'); - QString text = QStringLiteral(" ") + names.leftJustified(longestOptionNameString) + QLatin1Char(' '); + QString text = QLatin1String(" ") + names.leftJustified(longestOptionNameString) + QLatin1Char(' '); const int indent = text.length(); int lineStart = 0; int lastBreakable = -1; diff --git a/src/corelib/tools/qtimezoneprivate_win.cpp b/src/corelib/tools/qtimezoneprivate_win.cpp index 0984949286..1d19f01b4e 100644 --- a/src/corelib/tools/qtimezoneprivate_win.cpp +++ b/src/corelib/tools/qtimezoneprivate_win.cpp @@ -378,7 +378,7 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId) m_standardName = readRegistryString(baseKey, L"Std"); m_daylightName = readRegistryString(baseKey, L"Dlt"); // On Vista and later the optional dynamic key holds historic data - const QString dynamicKeyPath = baseKeyPath + QStringLiteral("\\Dynamic DST"); + const QString dynamicKeyPath = baseKeyPath + QLatin1String("\\Dynamic DST"); HKEY dynamicKey = NULL; if (openRegistryKey(dynamicKeyPath, &dynamicKey)) { // Find out the start and end years stored, then iterate over them From 97965a0908b8fbf7f01d0880410929a4ea61b48d Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Wed, 24 Feb 2016 15:53:59 +0300 Subject: [PATCH 118/118] QtGui: use reserve to optimize memory allocation. Change-Id: I34a571b67840557de19ab496cadebd698c7f4f6a Reviewed-by: Marc Mutz --- src/gui/kernel/qhighdpiscaling_p.h | 2 ++ src/gui/kernel/qwindowsysteminterface.cpp | 2 +- src/gui/text/qfontsubset.cpp | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h index 60e8dcf562..fe71de6c27 100644 --- a/src/gui/kernel/qhighdpiscaling_p.h +++ b/src/gui/kernel/qhighdpiscaling_p.h @@ -473,6 +473,7 @@ QVector fromNativePixels(const QVector &pixelValues, const QWindow *window return pixelValues; QVector pointValues; + pointValues.reserve(pixelValues.size()); for (const T &pixelValue : pixelValues) pointValues.append(pixelValue / QHighDpiScaling::factor(window)); return pointValues; @@ -486,6 +487,7 @@ QVector toNativePixels(const QVector &pointValues, const QWindow *window) return pointValues; QVector pixelValues; + pixelValues.reserve(pointValues.size()); for (const T &pointValue : pointValues) pixelValues.append(pointValue * QHighDpiScaling::factor(window)); return pixelValues; diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index c76721f89b..39bc161a7c 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -928,7 +928,7 @@ static QWindowSystemInterface::TouchPoint touchPoint(const QTouchEvent::TouchPoi static QList touchPointList(const QList& pointList) { QList newList; - + newList.reserve(pointList.size()); for (const QTouchEvent::TouchPoint &p : pointList) newList.append(touchPoint(p)); diff --git a/src/gui/text/qfontsubset.cpp b/src/gui/text/qfontsubset.cpp index 34db39e4a8..a9387e5aa0 100644 --- a/src/gui/text/qfontsubset.cpp +++ b/src/gui/text/qfontsubset.cpp @@ -624,6 +624,7 @@ static QTtfTable generateName(const QVector &name); static QTtfTable generateName(const qttf_name_table &name) { QVector list; + list.reserve(5); QTtfNameRecord rec; rec.nameId = 0; rec.value = name.copyright; @@ -1061,6 +1062,7 @@ static QVector generateGlyphTables(qttf_font_tables &tables, const QV Q_ASSERT(hmtx.data.size() == hs.offset()); QVector list; + list.reserve(3); list.append(glyf); list.append(loca); list.append(hmtx);