From 367680679ae13faaf71aa481265cb93629a36427 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 25 Aug 2014 12:56:34 +0200 Subject: [PATCH 01/89] Fix advance of zero-width spaces in fonts that omits the glyph Some fonts appear to include zero-width space in the CMAP table, but not include an actual definitions of the glyph they point to. The missing glyph causes a warning, but isn't handled making the character end up being giving the same metrics as whatever character it came after. This patch adds explicit handling of missing glyphs, and also caches their missing state when caching is enabled. Task-number: QTBUG-40912 Change-Id: I06fba9c01df59548e750e36babfdd5a6bafd6bd0 Reviewed-by: Konstantin Ritt Reviewed-by: Pierre Rossi --- src/gui/text/qfontengine_ft.cpp | 25 ++++++++++++++++++------- src/gui/text/qfontengine_ft_p.h | 3 +++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index cb3cb34d27..0a22038bb4 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -132,6 +132,7 @@ static bool ft_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *leng return result; } +static QFontEngineFT::Glyph emptyGlyph = {0, 0, 0, 0, 0, 0, 0, 0}; // -------------------------- Freetype support ------------------------------ @@ -858,6 +859,9 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, if (g && g->format == format && (fetchMetricsOnly || g->data)) return g; + if (!g && set && set->isGlyphMissing(glyph)) + return &emptyGlyph; + QFontEngineFT::GlyphInfo info; Q_ASSERT(format != Format_None); @@ -894,8 +898,12 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, load_flags |= FT_LOAD_FORCE_AUTOHINT; err = FT_Load_Glyph(face, glyph, load_flags); } - if (err != FT_Err_Ok) + if (err != FT_Err_Ok) { qWarning("load glyph failed err=%x face=%p, glyph=%d", err, face, glyph); + if (set) + set->setGlyphMissing(glyph); + return &emptyGlyph; + } FT_GlyphSlot slot = face->glyph; @@ -1633,9 +1641,12 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlag if (!face) face = lockFace(); g = loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyphs->glyphs[i], 0, Format_None, true); - glyphs->advances[i] = design ? QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10) - : QFixed::fromFixed(face->glyph->metrics.horiAdvance).round(); - if (!cacheEnabled) + if (g) + glyphs->advances[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance); + else + glyphs->advances[i] = design ? QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10) + : QFixed::fromFixed(face->glyph->metrics.horiAdvance).round(); + if (!cacheEnabled && g != &emptyGlyph) delete g; } } @@ -1674,7 +1685,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs) xmax = qMax(xmax, x + g->width); ymax = qMax(ymax, y + g->height); overall.xoff += g->advance; - if (!cacheEnabled) + if (!cacheEnabled && g != &emptyGlyph) delete g; } else { int left = FLOOR(face->glyph->metrics.horiBearingX); @@ -1717,7 +1728,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph) overall.xoff = g->advance; if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) overall.xoff = overall.xoff.round(); - if (!cacheEnabled) + if (!cacheEnabled && g != &emptyGlyph) delete g; } else { int left = FLOOR(face->glyph->metrics.horiBearingX); @@ -1808,7 +1819,7 @@ glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, QFixed subPixe overall.width = g->width; overall.height = g->height; overall.xoff = g->advance; - if (!glyphSet) + if (!glyphSet && g != &emptyGlyph) delete g; } else { int left = FLOOR(face->glyph->metrics.horiBearingX); diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index 09c70c5083..e23024e472 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -187,8 +187,11 @@ public: inline Glyph *getGlyph(glyph_t index, QFixed subPixelPosition = 0) const; void setGlyph(glyph_t index, QFixed spp, Glyph *glyph); + inline bool isGlyphMissing(glyph_t index) const { return missing_glyphs.contains(index); } + inline void setGlyphMissing(glyph_t index) const { missing_glyphs.insert(index); } private: mutable QHash glyph_data; // maps from glyph index to glyph data + mutable QSet missing_glyphs; mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256 mutable int fast_glyph_count; }; From 78ee7597482a2efa06305d659a88122a95a062de Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 27 Aug 2014 11:57:34 +0200 Subject: [PATCH 02/89] Windows QPA plugin: Streamline code to find window at a position. Task-number: QTBUG-40815 Change-Id: I0efcc2cfcafdee04bda20afa88a7f6aaabd57210 Reviewed-by: Kai Koehne Reviewed-by: Friedemann Kleint --- .../windows/qwindowsmousehandler.cpp | 2 +- .../platforms/windows/qwindowsscreen.cpp | 20 +++++-------------- .../platforms/windows/qwindowsscreen.h | 8 ++------ .../windows/qwindowstabletsupport.cpp | 4 ++-- .../platforms/windows/qwindowswindow.cpp | 20 ------------------- .../platforms/windows/qwindowswindow.h | 5 ----- 6 files changed, 10 insertions(+), 49 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 2e677102a5..96c4a8bb78 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -384,7 +384,7 @@ bool QWindowsMouseHandler::translateMouseWheelEvent(QWindow *window, HWND, // 2) The window receiving the event // If a window is blocked by modality, it can't get the event. const QPoint globalPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam)); - QWindow *receiver = QWindowsScreen::windowAt(globalPos); + QWindow *receiver = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE); bool handleEvent = true; if (!isValidWheelReceiver(receiver)) { receiver = window; diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index a5a291a8d8..796975122e 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -287,13 +287,12 @@ QPixmap QWindowsScreen::grabWindow(WId window, int qX, int qY, int qWidth, int q \brief Find a top level window taking the flags of ChildWindowFromPointEx. */ -QWindow *QWindowsScreen::findTopLevelAt(const QPoint &point, unsigned flags) +QWindow *QWindowsScreen::topLevelAt(const QPoint &point) const { - QWindow* result = 0; - if (QPlatformWindow *bw = QWindowsContext::instance()-> - findPlatformWindowAt(GetDesktopWindow(), point, flags)) - result = QWindowsWindow::topLevelOf(bw->window()); - qCDebug(lcQpaWindows) <<__FUNCTION__ << point << flags << result; + QWindow *result = 0; + if (QWindow *child = QWindowsScreen::windowAt(point * QWindowsScaling::factor(), CWP_SKIPINVISIBLE)) + result = QWindowsWindow::topLevelOf(child); + qCDebug(lcQpaWindows) <<__FUNCTION__ << point << result; return result; } @@ -307,15 +306,6 @@ QWindow *QWindowsScreen::windowAt(const QPoint &screenPoint, unsigned flags) return result; } -QWindow *QWindowsScreen::windowUnderMouse(unsigned flags) -{ -#ifndef QT_NO_CURSOR - return QWindowsScreen::windowAt(QWindowsCursor::mousePosition(), flags); -#else - return 0; -#endif -} - QWindowsScreen *QWindowsScreen::screenOf(const QWindow *w) { if (w) diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h index 49581db41a..44638bcbe0 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -104,12 +104,8 @@ public: QString name() const Q_DECL_OVERRIDE { return m_data.name; } Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE { return m_data.orientation; } QList virtualSiblings() const Q_DECL_OVERRIDE; - QWindow *topLevelAt(const QPoint &point) const Q_DECL_OVERRIDE - { return QWindowsScreen::findTopLevelAt(point * QWindowsScaling::factor() , CWP_SKIPINVISIBLE); } - - static QWindow *findTopLevelAt(const QPoint &point, unsigned flags); - static QWindow *windowAt(const QPoint &point, unsigned flags = CWP_SKIPINVISIBLE); - static QWindow *windowUnderMouse(unsigned flags = CWP_SKIPINVISIBLE); + QWindow *topLevelAt(const QPoint &point) const Q_DECL_OVERRIDE; + static QWindow *windowAt(const QPoint &point, unsigned flags); QPixmap grabWindow(WId window, int qX, int qY, int qWidth, int qHeight) const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp index 7d020ff9d6..b6940e6850 100644 --- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp +++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp @@ -47,6 +47,7 @@ #include "qwindowscontext.h" #include "qwindowskeymapper.h" #include "qwindowswindow.h" +#include "qwindowsscreen.h" #include @@ -437,8 +438,7 @@ bool QWindowsTabletSupport::translateTabletPacketEvent() } if (!target) - if (QPlatformWindow *pw = QWindowsContext::instance()->findPlatformWindowAt(GetDesktopWindow(), globalPos, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT)) - target = pw->window(); + target = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT); if (!target) continue; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index e6b996c685..672d169984 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -2083,26 +2083,6 @@ void QWindowsWindow::setCursor(const QWindowsWindowCursor &c) #endif } -/*! - \brief Find a child window using flags from ChildWindowFromPointEx. -*/ - -QWindowsWindow *QWindowsWindow::childAtScreenPoint(const QPoint &screenPoint, - unsigned cwexflags) const -{ - if (m_data.hwnd) - return QWindowsContext::instance()->findPlatformWindowAt(m_data.hwnd, screenPoint, cwexflags); - return 0; -} - -QWindowsWindow *QWindowsWindow::childAt(const QPoint &clientPoint, unsigned cwexflags) const -{ - if (m_data.hwnd) - return childAtScreenPoint(QWindowsGeometryHint::mapToGlobal(m_data.hwnd, clientPoint), - cwexflags); - return 0; -} - #ifndef Q_OS_WINCE void QWindowsWindow::setAlertState(bool enabled) { diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index cb9da6fe27..03c71351bd 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -246,11 +246,6 @@ public: void setCursor(const QWindowsWindowCursor &c); void applyCursor(); - QWindowsWindow *childAt(const QPoint &clientPoint, - unsigned cwexflags = CWP_SKIPINVISIBLE) const; - QWindowsWindow *childAtScreenPoint(const QPoint &screenPoint, - unsigned cwexflags = CWP_SKIPINVISIBLE) const; - static QByteArray debugWindowFlags(Qt::WindowFlags wf); inline bool testFlag(unsigned f) const { return (m_flags & f) != 0; } From d06fb5609c02d639e44e932988f428c13aab71c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 25 Jul 2014 15:27:23 +0200 Subject: [PATCH 03/89] iOS: Initialize QScreen properties before setting up root viewcontroller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I5fd899030b0557e9b0d96f2c065c8be5cfadd5de Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosscreen.mm | 38 ++++++++++++------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index e876665431..a814c042c7 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -184,25 +184,6 @@ QIOSScreen::QIOSScreen(UIScreen *screen) , m_uiWindow(0) , m_orientationListener(0) { - for (UIWindow *existingWindow in [[UIApplication sharedApplication] windows]) { - if (existingWindow.screen == m_uiScreen) { - m_uiWindow = [m_uiWindow retain]; - break; - } - } - - if (!m_uiWindow) { - // Create a window and associated view-controller that we can use - m_uiWindow = [[UIWindow alloc] initWithFrame:[m_uiScreen bounds]]; - m_uiWindow.rootViewController = [[[QIOSViewController alloc] initWithQIOSScreen:this] autorelease]; - - // FIXME: Only do once windows are added to the screen, and for any screen - if (screen == [UIScreen mainScreen]) { - m_uiWindow.screen = m_uiScreen; - m_uiWindow.hidden = NO; - } - } - if (screen == [UIScreen mainScreen]) { QString deviceIdentifier = deviceModelIdentifier(); @@ -225,6 +206,25 @@ QIOSScreen::QIOSScreen(UIScreen *screen) m_unscaledDpi = 96; } + for (UIWindow *existingWindow in [[UIApplication sharedApplication] windows]) { + if (existingWindow.screen == m_uiScreen) { + m_uiWindow = [m_uiWindow retain]; + break; + } + } + + if (!m_uiWindow) { + // Create a window and associated view-controller that we can use + m_uiWindow = [[UIWindow alloc] initWithFrame:[m_uiScreen bounds]]; + m_uiWindow.rootViewController = [[[QIOSViewController alloc] initWithQIOSScreen:this] autorelease]; + + // FIXME: Only do once windows are added to the screen, and for any screen + if (screen == [UIScreen mainScreen]) { + m_uiWindow.screen = m_uiScreen; + m_uiWindow.hidden = NO; + } + } + connect(qGuiApp, &QGuiApplication::focusWindowChanged, this, &QIOSScreen::updateStatusBarVisibility); updateProperties(); From da2b3c4479e1d23ea6ead555cadc96a56967887a Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 1 Sep 2014 10:43:42 +0200 Subject: [PATCH 04/89] Prevent current context from becoming inconsistent upon create() Platform plugins have a tendency to make the newly created native context current with a temporary surface. This is usually needed to query some information related to the new context. Afterwards most of them just reset to having nothing current. This has two issues: It unexpectedly changes the current context/surface. A call into QOpenGLContext::create() does not imply that the current context will get changed. This is the minor issue and we could probably live with it (at least if it had been documented). However, the real issue is that QOpenGLContext::currentContext() will become inconsistent: it will still report whatever was current before the create() even though on the EGL/WGL/GLX level that's not the case anymore. To prevent all this confusion the platform plugins can easily be changed to restore whatever context/surface was current before they altered it. Change-Id: I6a5b4597c86571327524ddb13e0d02538593cc7b Reviewed-by: Friedemann Kleint Reviewed-by: Gunnar Sletta --- .../eglconvenience/qeglplatformcontext.cpp | 11 ++++++++++- src/plugins/platforms/windows/qwindowseglcontext.cpp | 9 ++++++++- src/plugins/platforms/windows/qwindowsglcontext.cpp | 5 ++++- src/plugins/platforms/xcb/qglxintegration.cpp | 10 ++++++---- 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp index 148c5d9b2f..dce8bd888c 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp @@ -249,6 +249,15 @@ void QEGLPlatformContext::adopt(const QVariant &nativeHandle, QPlatformOpenGLCon void QEGLPlatformContext::updateFormatFromGL() { #ifndef QT_NO_OPENGL + // Have to save & restore to prevent QOpenGLContext::currentContext() from becoming + // inconsistent after QOpenGLContext::create(). + EGLDisplay prevDisplay = eglGetCurrentDisplay(); + if (prevDisplay == EGL_NO_DISPLAY) // when no context is current + prevDisplay = m_eglDisplay; + EGLContext prevContext = eglGetCurrentContext(); + EGLSurface prevSurfaceDraw = eglGetCurrentSurface(EGL_DRAW); + EGLSurface prevSurfaceRead = eglGetCurrentSurface(EGL_READ); + // Make the context current to ensure the GL version query works. This needs a surface too. const EGLint pbufferAttributes[] = { EGL_WIDTH, 1, @@ -300,7 +309,7 @@ void QEGLPlatformContext::updateFormatFromGL() } } } - eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglMakeCurrent(prevDisplay, prevSurfaceDraw, prevSurfaceRead, prevContext); } eglDestroySurface(m_eglDisplay, pbuffer); #endif // QT_NO_OPENGL diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index c62875d0ef..2d2d409a0f 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -512,6 +512,13 @@ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext, if (pbuffer == EGL_NO_SURFACE) return; + EGLDisplay prevDisplay = eglGetCurrentDisplay(); + if (prevDisplay == EGL_NO_DISPLAY) // when no context is current + prevDisplay = m_eglDisplay; + EGLContext prevContext = eglGetCurrentContext(); + EGLSurface prevSurfaceDraw = eglGetCurrentSurface(EGL_DRAW); + EGLSurface prevSurfaceRead = eglGetCurrentSurface(EGL_READ); + if (QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, pbuffer, pbuffer, m_eglContext)) { const GLubyte *s = QWindowsEGLStaticContext::libGLESv2.glGetString(GL_VERSION); if (s) { @@ -524,7 +531,7 @@ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext, } m_format.setProfile(QSurfaceFormat::NoProfile); m_format.setOptions(QSurfaceFormat::FormatOptions()); - QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + QWindowsEGLStaticContext::libEGL.eglMakeCurrent(prevDisplay, prevSurfaceDraw, prevSurfaceRead, prevContext); } QWindowsEGLStaticContext::libEGL.eglDestroySurface(m_eglDisplay, pbuffer); } diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index e09018ef69..1ed27f545d 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -1207,6 +1207,9 @@ QWindowsGLContext::~QWindowsGLContext() bool QWindowsGLContext::updateObtainedParams(HDC hdc, int *obtainedSwapInterval) { + HGLRC prevContext = wglGetCurrentContext(); + HDC prevSurface = wglGetCurrentDC(); + if (!QOpenGLStaticContext::opengl32.wglMakeCurrent(hdc, m_renderingContext)) { qWarning("Failed to make context current."); return false; @@ -1217,7 +1220,7 @@ bool QWindowsGLContext::updateObtainedParams(HDC hdc, int *obtainedSwapInterval) if (m_staticContext->wglGetSwapInternalExt && obtainedSwapInterval) *obtainedSwapInterval = m_staticContext->wglGetSwapInternalExt(); - QOpenGLStaticContext::opengl32.wglMakeCurrent(0, 0); + QOpenGLStaticContext::opengl32.wglMakeCurrent(prevSurface, prevContext); return true; } diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp index d6fe5f3477..3b13df863e 100644 --- a/src/plugins/platforms/xcb/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -323,11 +323,11 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share) // Query the OpenGL version and profile if (m_context && window) { + GLXContext prevContext = glXGetCurrentContext(); + GLXDrawable prevDrawable = glXGetCurrentDrawable(); glXMakeCurrent(DISPLAY_FROM_XCB(screen), window, m_context); updateFormatFromContext(m_format); - - // Make our context non-current - glXMakeCurrent(DISPLAY_FROM_XCB(screen), 0, 0); + glXMakeCurrent(DISPLAY_FROM_XCB(screen), prevDrawable, prevContext); } // Destroy our temporary window @@ -419,6 +419,8 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const } // Update OpenGL version and buffer sizes in our format. + GLXContext prevContext = glXGetCurrentContext(); + GLXDrawable prevDrawable = glXGetCurrentDrawable(); if (!glXMakeCurrent(dpy, window, context)) { qWarning("QGLXContext: Failed to make provided context current"); return; @@ -431,7 +433,7 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const qglx_surfaceFormatFromVisualInfo(&m_format, dpy, vinfo); else qglx_surfaceFormatFromGLXFBConfig(&m_format, dpy, config); - glXMakeCurrent(dpy, 0, 0); + glXMakeCurrent(dpy, prevDrawable, prevContext); XDestroyWindow(dpy, window); if (vinfo) From 552ac4bcb69d146c35e0b8adc83f3634d84a1d18 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 1 Sep 2014 08:11:27 +0300 Subject: [PATCH 05/89] ANGLE: Don't directly link to DirectX 11 These libraries are dynamically loaded on desktop Windows. Change-Id: I3a0d17a48a3bd4930690d20d387df0d92906662d Reviewed-by: Friedemann Kleint --- src/angle/src/libEGL/libEGL.pro | 5 +---- src/angle/src/libGLESv2/libGLESv2.pro | 4 +--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/angle/src/libEGL/libEGL.pro b/src/angle/src/libEGL/libEGL.pro index dc286ca11d..48ce7055fd 100644 --- a/src/angle/src/libEGL/libEGL.pro +++ b/src/angle/src/libEGL/libEGL.pro @@ -1,10 +1,7 @@ CONFIG += installed include(../common/common.pri) -angle_d3d11: \ - LIBS_PRIVATE += -ld3d11 -!winrt: \ - LIBS_PRIVATE += -ld3d9 +winrt: LIBS_PRIVATE += -ld3d11 LIBS_PRIVATE += -ldxguid -L$$QT_BUILD_TREE/lib -l$$qtLibraryTarget(libGLESv2) diff --git a/src/angle/src/libGLESv2/libGLESv2.pro b/src/angle/src/libGLESv2/libGLESv2.pro index 8109c34942..2e84df0d39 100644 --- a/src/angle/src/libGLESv2/libGLESv2.pro +++ b/src/angle/src/libGLESv2/libGLESv2.pro @@ -4,12 +4,10 @@ include(../common/common.pri) INCLUDEPATH += $$OUT_PWD/.. $$ANGLE_DIR/src/libGLESv2 # Remember to adapt tools/configure/configureapp.cpp if the Direct X version changes. -angle_d3d11: \ - LIBS_PRIVATE += -ldxgi -ld3d11 !winrt: \ LIBS_PRIVATE += -ld3d9 winrt: \ - LIBS_PRIVATE += -ld3dcompiler + LIBS_PRIVATE += -ld3dcompiler -ldxgi -ld3d11 LIBS_PRIVATE += -ldxguid From ffceaf62135e58cfc14d3d9fd058ff0c08baf1e9 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 1 Sep 2014 12:11:59 +0300 Subject: [PATCH 06/89] ANGLE: Fix -angle-d3d11 on MSVC2010 Allow the D3D11 renderer to build with the June 2010 DirectX SDK. Change-Id: I2343acedab16845d6a0d4a53cf3145f583efc4a7 Reviewed-by: Andreas Holzammer Reviewed-by: Friedemann Kleint --- src/3rdparty/angle/src/common/platform.h | 2 + .../libGLESv2/renderer/d3d/d3d11/Clear11.cpp | 4 +- .../renderer/d3d/d3d11/renderer11_utils.cpp | 49 +++++ ...15-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch | 203 ++++++++++++++++++ src/angle/src/config.pri | 2 +- 5 files changed, 257 insertions(+), 3 deletions(-) create mode 100644 src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h index cedc6f2f22..44c5c7c03b 100644 --- a/src/3rdparty/angle/src/common/platform.h +++ b/src/3rdparty/angle/src/common/platform.h @@ -59,8 +59,10 @@ # include # include # include +# if _MSC_VER >= 1700 # include # include +# endif # endif # undef near diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp index 8db5ea27c1..5121950da0 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp @@ -116,8 +116,8 @@ Clear11::Clear11(Renderer11 *renderer) mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat); if (mRenderer->isLevel9()) { - mUintClearShader = { 0 }; - mIntClearShader = { 0 }; + memset(&mUintClearShader, 0, sizeof(ClearShader)); + memset(&mIntClearShader, 0, sizeof(ClearShader)); return; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp index d3d135fe5b..8e0c21bd83 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp @@ -12,6 +12,31 @@ #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" #include "common/debug.h" +#ifndef D3D_FL9_1_DEFAULT_MAX_ANISOTROPY +# define D3D_FL9_1_DEFAULT_MAX_ANISOTROPY 2 +#endif +#ifndef D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT +# define D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT 1 +#endif +#ifndef D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT +# define D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT 4 +#endif +#ifndef D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION +# define D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION 512 +#endif +#ifndef D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION +# define D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION 4096 +#endif +#ifndef D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION +# define D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION 2048 +#endif +#ifndef D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION +# define D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 256 +#endif +#ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION +# define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096 +#endif + namespace rx { @@ -273,7 +298,9 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { +#if _MSC_VER >= 1700 case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return true; @@ -291,7 +318,9 @@ static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { +#if _MSC_VER >= 1700 case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY; case D3D_FEATURE_LEVEL_10_1: @@ -311,7 +340,9 @@ static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { +#if _MSC_VER >= 1700 case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return true; @@ -331,7 +362,9 @@ static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { +#if _MSC_VER >= 1700 case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: @@ -349,7 +382,9 @@ static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { +#if _MSC_VER >= 1700 case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: @@ -372,7 +407,9 @@ static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { +#if _MSC_VER >= 1700 case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: @@ -390,7 +427,9 @@ static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel switch (featureLevel) { +#if _MSC_VER >= 1700 case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; // FIXME(geofflang): Work around NVIDIA driver bug by repacking buffers @@ -409,7 +448,9 @@ static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { +#if _MSC_VER >= 1700 case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; case D3D_FEATURE_LEVEL_10_1: @@ -427,7 +468,9 @@ static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { +#if _MSC_VER >= 1700 case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION; case D3D_FEATURE_LEVEL_10_1: @@ -445,7 +488,9 @@ static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { +#if _MSC_VER >= 1700 case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; case D3D_FEATURE_LEVEL_10_1: @@ -463,7 +508,9 @@ static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { +#if _MSC_VER >= 1700 case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; case D3D_FEATURE_LEVEL_10_1: @@ -481,7 +528,9 @@ static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { +#if _MSC_VER >= 1700 case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX; case D3D_FEATURE_LEVEL_10_1: diff --git a/src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch b/src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch new file mode 100644 index 0000000000..dcff4a323e --- /dev/null +++ b/src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch @@ -0,0 +1,203 @@ +From bfcd8298f9ba074116de434bf252ea95be968a20 Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Mon, 1 Sep 2014 12:11:17 +0300 +Subject: [PATCH] ANGLE: Fix -angle-d3d11 on MSVC2010 + +Allow the D3D11 renderer to build with the June 2010 DirectX SDK. + +Change-Id: I2343acedab16845d6a0d4a53cf3145f583efc4a7 +--- + src/3rdparty/angle/src/common/platform.h | 2 + + .../src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp | 4 +- + .../renderer/d3d/d3d11/renderer11_utils.cpp | 49 ++++++++++++++++++++++ + 3 files changed, 53 insertions(+), 2 deletions(-) + +diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h +index cedc6f2..44c5c7c 100644 +--- a/src/3rdparty/angle/src/common/platform.h ++++ b/src/3rdparty/angle/src/common/platform.h +@@ -59,8 +59,10 @@ + # include + # include + # include ++# if _MSC_VER >= 1700 + # include + # include ++# endif + # endif + + # undef near +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp +index 8db5ea2..5121950 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp +@@ -116,8 +116,8 @@ Clear11::Clear11(Renderer11 *renderer) + + mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat); + if (mRenderer->isLevel9()) { +- mUintClearShader = { 0 }; +- mIntClearShader = { 0 }; ++ memset(&mUintClearShader, 0, sizeof(ClearShader)); ++ memset(&mIntClearShader, 0, sizeof(ClearShader)); + return; + } + +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp +index d3d135f..8e0c21b 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp +@@ -12,6 +12,31 @@ + #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" + #include "common/debug.h" + ++#ifndef D3D_FL9_1_DEFAULT_MAX_ANISOTROPY ++# define D3D_FL9_1_DEFAULT_MAX_ANISOTROPY 2 ++#endif ++#ifndef D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT ++# define D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT 1 ++#endif ++#ifndef D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT ++# define D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT 4 ++#endif ++#ifndef D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION ++# define D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION 512 ++#endif ++#ifndef D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION ++# define D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION 4096 ++#endif ++#ifndef D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION ++# define D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION 2048 ++#endif ++#ifndef D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION ++# define D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 256 ++#endif ++#ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION ++# define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096 ++#endif ++ + namespace rx + { + +@@ -273,7 +298,9 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if _MSC_VER >= 1700 + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; +@@ -291,7 +318,9 @@ static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if _MSC_VER >= 1700 + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY; + + case D3D_FEATURE_LEVEL_10_1: +@@ -311,7 +340,9 @@ static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if _MSC_VER >= 1700 + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; +@@ -331,7 +362,9 @@ static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) + + switch (featureLevel) + { ++#if _MSC_VER >= 1700 + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: +@@ -349,7 +382,9 @@ static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) + + switch (featureLevel) + { ++#if _MSC_VER >= 1700 + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: +@@ -372,7 +407,9 @@ static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) + + switch (featureLevel) + { ++#if _MSC_VER >= 1700 + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: +@@ -390,7 +427,9 @@ static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel + + switch (featureLevel) + { ++#if _MSC_VER >= 1700 + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; + + // FIXME(geofflang): Work around NVIDIA driver bug by repacking buffers +@@ -409,7 +448,9 @@ static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if _MSC_VER >= 1700 + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: +@@ -427,7 +468,9 @@ static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if _MSC_VER >= 1700 + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: +@@ -445,7 +488,9 @@ static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if _MSC_VER >= 1700 + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: +@@ -463,7 +508,9 @@ static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if _MSC_VER >= 1700 + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: +@@ -481,7 +528,9 @@ static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if _MSC_VER >= 1700 + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX; + + case D3D_FEATURE_LEVEL_10_1: +-- +1.9.0.msysgit.0 + diff --git a/src/angle/src/config.pri b/src/angle/src/config.pri index ccc4cb16a1..88c65802de 100644 --- a/src/angle/src/config.pri +++ b/src/angle/src/config.pri @@ -37,7 +37,7 @@ DEFINES += _WINDOWS \ NOMINMAX \ WIN32_LEAN_AND_MEAN=1 -!winrt: DEFINES += ANGLE_ENABLE_D3D9 +!winrt: DEFINES += ANGLE_ENABLE_D3D9 ANGLE_SKIP_DXGI_1_2_CHECK angle_d3d11 { DEFINES += ANGLE_ENABLE_D3D11 ANGLE_DEFAULT_D3D11=1 From 6ae01c72e1634d41e4775e6cec0089c8d49da29c Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 29 Aug 2014 17:57:49 +0200 Subject: [PATCH 07/89] Fix no-opengl build Change-Id: I577bd5d10e52571c95c9e646327264cf95ac6eb1 Reviewed-by: Andrew Knight Reviewed-by: Friedemann Kleint --- src/gui/kernel/qopenglwindow.h | 6 ++++++ src/plugins/platforms/platforms.pro | 2 +- src/widgets/kernel/qopenglwidget.h | 6 ++++++ src/widgets/kernel/qwidget.cpp | 8 ++++++++ src/widgets/kernel/qwidgetbackingstore.cpp | 5 +++++ src/widgets/widgets/qabstractscrollarea.cpp | 2 ++ 6 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qopenglwindow.h b/src/gui/kernel/qopenglwindow.h index 294bd90116..e30de3b6ac 100644 --- a/src/gui/kernel/qopenglwindow.h +++ b/src/gui/kernel/qopenglwindow.h @@ -42,6 +42,10 @@ #ifndef QOPENGLWINDOW_H #define QOPENGLWINDOW_H +#include + +#ifndef QT_NO_OPENGL + #include #include #include @@ -97,4 +101,6 @@ private: QT_END_NAMESPACE +#endif // QT_NO_OPENGL + #endif diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro index 584efa1665..69f6f308b5 100644 --- a/src/plugins/platforms/platforms.pro +++ b/src/plugins/platforms/platforms.pro @@ -35,7 +35,7 @@ contains(QT_CONFIG, directfb) { SUBDIRS += directfb } -contains(QT_CONFIG, kms) { +contains(QT_CONFIG, kms):contains(QT_CONFIG, opengl) { SUBDIRS += kms } diff --git a/src/widgets/kernel/qopenglwidget.h b/src/widgets/kernel/qopenglwidget.h index 28d802e1f4..f706ea7567 100644 --- a/src/widgets/kernel/qopenglwidget.h +++ b/src/widgets/kernel/qopenglwidget.h @@ -42,6 +42,10 @@ #ifndef QOPENGLWIDGET_H #define QOPENGLWIDGET_H +#include + +#ifndef QT_NO_OPENGL + #include #include #include @@ -97,4 +101,6 @@ private: QT_END_NAMESPACE +#endif // QT_NO_OPENGL + #endif // QOPENGLWIDGET_H diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 34adea866e..21278a0ba9 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -5486,22 +5486,30 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP //paint the background if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground)) && !q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) { +#ifndef QT_NO_OPENGL beginBackingStorePainting(); +#endif QPainter p(q); paintBackground(&p, toBePainted, (asRoot || onScreen) ? flags | DrawAsRoot : 0); +#ifndef QT_NO_OPENGL endBackingStorePainting(); +#endif } if (!sharedPainter) setSystemClip(pdev, toBePainted.translated(offset)); if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) { +#ifndef QT_NO_OPENGL beginBackingStorePainting(); +#endif QPainter p(q); QColor tint = q->palette().window().color(); tint.setAlphaF(qreal(.6)); p.fillRect(toBePainted.boundingRect(), tint); +#ifndef QT_NO_OPENGL endBackingStorePainting(); +#endif } } diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 2a968939e4..103e244593 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -1158,6 +1158,7 @@ void QWidgetBackingStore::doSync() return; } +#ifndef QT_NO_OPENGL // There is something other dirty than the renderToTexture widgets. // Now it is time to include the renderToTexture ones among the others. if (widgetTextures && widgetTextures->count()) { @@ -1167,6 +1168,8 @@ void QWidgetBackingStore::doSync() toClean += rect; } } +#endif + // The dirtyRenderToTextureWidgets list is useless here, so just reset. As // unintuitive as it is, we need to send paint events to renderToTexture // widgets always when something (any widget) needs to be updated, even if @@ -1249,8 +1252,10 @@ void QWidgetBackingStore::flush(QWidget *widget) QWidget *target = widget ? widget : tlw; qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset, widgetTextures, this); dirtyOnScreen = QRegion(); +#ifndef QT_NO_OPENGL if (widgetTextures && widgetTextures->count()) return; +#endif } if (!dirtyOnScreenWidgets || dirtyOnScreenWidgets->isEmpty()) { diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp index 1b48441993..0e78c1493b 100644 --- a/src/widgets/widgets/qabstractscrollarea.cpp +++ b/src/widgets/widgets/qabstractscrollarea.cpp @@ -1191,10 +1191,12 @@ bool QAbstractScrollArea::viewportEvent(QEvent *e) case QEvent::DragMove: case QEvent::DragLeave: #endif +#ifndef QT_NO_OPENGL // QOpenGLWidget needs special support because it has to know // its size has changed, so that it can resize its fbo. if (e->type() == QEvent::Resize) QWidgetPrivate::get(viewport())->resizeViewportFramebuffer(); +#endif return QFrame::event(e); case QEvent::LayoutRequest: #ifndef QT_NO_GESTURES From fc3acdd9d2766637e0410f7de83b63116df7e053 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 1 Sep 2014 15:47:16 +0300 Subject: [PATCH 08/89] winrt: Fix mouse coordinates on high-DPI displays The scale factor was only being applied to touch coordinates. Change-Id: I7fc2793b1514c73986a574a95478306c1eb54c5e Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtscreen.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 6c905735dd..b981b94748 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -828,12 +828,14 @@ HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *, ICharacterReceivedEvent HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *, IPointerEventArgs *args) { + Q_D(QWinRTScreen); + ComPtr pointerPoint; if (SUCCEEDED(args->get_CurrentPoint(&pointerPoint))) { // Assumes full-screen window Point point; pointerPoint->get_Position(&point); - QPoint pos(point.X, point.Y); + QPoint pos(point.X * d->scaleFactor, point.Y * d->scaleFactor); QWindowSystemInterface::handleEnterEvent(topWindow(), pos, pos); } @@ -856,7 +858,7 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args) // Common traits - point, modifiers, properties Point point; pointerPoint->get_Position(&point); - QPointF pos(point.X, point.Y); + QPointF pos(point.X * d->scaleFactor, point.Y * d->scaleFactor); VirtualKeyModifiers modifiers; args->get_KeyModifiers(&modifiers); @@ -954,7 +956,7 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args) } it.value().area = QRectF(area.X * d->scaleFactor, area.Y * d->scaleFactor, area.Width * d->scaleFactor, area.Height * d->scaleFactor); - it.value().normalPosition = QPointF(pos.x()/d->logicalSize.width(), pos.y()/d->logicalSize.height()); + it.value().normalPosition = QPointF(point.X/d->logicalSize.width(), point.Y/d->logicalSize.height()); it.value().pressure = pressure; QWindowSystemInterface::handleTouchEvent(topWindow(), d->touchDevice, d->touchPoints.values(), mods); From 1cdcf64ad5c0f42d23ad1a53c965df5c69a6bb4b Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Wed, 27 Aug 2014 16:23:28 +0300 Subject: [PATCH 09/89] direct2d: Fix translucent/frameless window rendering When using WA_TranslucentBackground/FramelessWindowHint, the backing store must paint to an offscreen texture instead of the swap chain in order to achieve the desired results. This texture is then presented to the screen using UpdateLayeredWindowIndirect(). As the swap chain is not needed in this mode, its construction is skipped if indirect rendering is active. Furthermore, the layering options were updated to fix an issue with transparent layers overpainting the background. The layer options were switched to D2D1_LAYER_OPTIONS1_NONE, which appears to work for both translucent and non-translucent rendering modes. Task-number: QTBUG-40601 Change-Id: I656f7cdfb424d1eda6f82c2c69500e78d8c1726a Reviewed-by: Louai Al-Khanji Reviewed-by: Friedemann Kleint --- .../direct2d/qwindowsdirect2dbackingstore.cpp | 16 +- .../direct2d/qwindowsdirect2dpaintengine.cpp | 4 +- .../direct2d/qwindowsdirect2dwindow.cpp | 222 ++++++++++++------ .../direct2d/qwindowsdirect2dwindow.h | 6 +- 4 files changed, 171 insertions(+), 77 deletions(-) diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp index be013f027b..59b543e6d5 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp @@ -49,6 +49,7 @@ #include "qwindowscontext.h" +#include #include #include @@ -85,9 +86,18 @@ QWindowsDirect2DBackingStore::~QWindowsDirect2DBackingStore() { } -void QWindowsDirect2DBackingStore::beginPaint(const QRegion &) +void QWindowsDirect2DBackingStore::beginPaint(const QRegion ®ion) { - bitmap(nativeWindow(window())->pixmap())->deviceContext()->begin(); + QPixmap *pixmap = nativeWindow(window())->pixmap(); + bitmap(pixmap)->deviceContext()->begin(); + + QPainter painter(pixmap); + QColor clear(Qt::transparent); + + painter.setCompositionMode(QPainter::CompositionMode_Source); + + foreach (const QRect &r, region.rects()) + painter.fillRect(r, clear); } void QWindowsDirect2DBackingStore::endPaint() @@ -107,7 +117,7 @@ void QWindowsDirect2DBackingStore::flush(QWindow *targetWindow, const QRegion &r nativeWindow(targetWindow)->flush(copy.data(), region, offset); } - nativeWindow(targetWindow)->present(); + nativeWindow(targetWindow)->present(region); } void QWindowsDirect2DBackingStore::resize(const QSize &size, const QRegion ®ion) diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index f131419140..a4e75f6571 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp @@ -343,7 +343,7 @@ public: D2D1::IdentityMatrix(), 1.0, NULL, - D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND), + D2D1_LAYER_OPTIONS1_NONE), NULL); pushedClips.push(LayerClip); } @@ -953,7 +953,7 @@ bool QWindowsDirect2DPaintEngine::begin(QPaintDevice * pdev) D2D1::IdentityMatrix(), 1.0, NULL, - D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND), + D2D1_LAYER_OPTIONS1_NONE), NULL); } else { QRect clip(0, 0, pdev->width(), pdev->height()); diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp index 15ec0c3526..37987931b3 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp @@ -54,10 +54,135 @@ QT_BEGIN_NAMESPACE QWindowsDirect2DWindow::QWindowsDirect2DWindow(QWindow *window, const QWindowsWindowData &data) : QWindowsWindow(window, data) , m_needsFullFlush(true) + , m_directRendering(!(data.flags & Qt::FramelessWindowHint && window->format().hasAlpha())) { if (window->type() == Qt::Desktop) return; // No further handling for Qt::Desktop + if (m_directRendering) + setupSwapChain(); + + HRESULT hr = QWindowsDirect2DContext::instance()->d2dDevice()->CreateDeviceContext( + D2D1_DEVICE_CONTEXT_OPTIONS_NONE, + m_deviceContext.GetAddressOf()); + if (FAILED(hr)) + qWarning("%s: Couldn't create Direct2D Device context: %#x", __FUNCTION__, hr); +} + +QWindowsDirect2DWindow::~QWindowsDirect2DWindow() +{ +} + +void QWindowsDirect2DWindow::setWindowFlags(Qt::WindowFlags flags) +{ + m_directRendering = !(flags & Qt::FramelessWindowHint && window()->format().hasAlpha()); + if (!m_directRendering) + m_swapChain.Reset(); // No need for the swap chain; release from memory + else if (!m_swapChain) + setupSwapChain(); + + QWindowsWindow::setWindowFlags(flags); +} + +QPixmap *QWindowsDirect2DWindow::pixmap() +{ + setupBitmap(); + + return m_pixmap.data(); +} + +void QWindowsDirect2DWindow::flush(QWindowsDirect2DBitmap *bitmap, const QRegion ®ion, const QPoint &offset) +{ + QSize size; + if (m_directRendering) { + DXGI_SWAP_CHAIN_DESC1 desc; + HRESULT hr = m_swapChain->GetDesc1(&desc); + QRect geom = geometry(); + + if ((FAILED(hr) || (desc.Width != geom.width()) || (desc.Height != geom.height()))) { + resizeSwapChain(geom.size()); + m_swapChain->GetDesc1(&desc); + } + size.setWidth(desc.Width); + size.setHeight(desc.Height); + } else { + size = geometry().size(); + } + + setupBitmap(); + if (!m_bitmap) + return; + + if (bitmap != m_bitmap.data()) { + m_bitmap->deviceContext()->begin(); + + ID2D1DeviceContext *dc = m_bitmap->deviceContext()->get(); + if (!m_needsFullFlush) { + QRegion clipped = region; + clipped &= QRect(QPoint(), size); + + foreach (const QRect &rect, clipped.rects()) { + QRectF rectF(rect); + dc->DrawBitmap(bitmap->bitmap(), + to_d2d_rect_f(rectF), + 1.0, + D2D1_INTERPOLATION_MODE_LINEAR, + to_d2d_rect_f(rectF.translated(offset.x(), offset.y()))); + } + } else { + QRectF rectF(QPoint(), size); + dc->DrawBitmap(bitmap->bitmap(), + to_d2d_rect_f(rectF), + 1.0, + D2D1_INTERPOLATION_MODE_LINEAR, + to_d2d_rect_f(rectF.translated(offset.x(), offset.y()))); + m_needsFullFlush = false; + } + + m_bitmap->deviceContext()->end(); + } +} + +void QWindowsDirect2DWindow::present(const QRegion ®ion) +{ + if (m_directRendering) { + m_swapChain->Present(0, 0); + return; + } + + ComPtr bitmapSurface; + HRESULT hr = m_bitmap->bitmap()->GetSurface(&bitmapSurface); + Q_ASSERT(SUCCEEDED(hr)); + ComPtr dxgiSurface; + hr = bitmapSurface.As(&dxgiSurface); + Q_ASSERT(SUCCEEDED(hr)); + + HDC hdc; + hr = dxgiSurface->GetDC(FALSE, &hdc); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get DC for presenting the surface"); + return; + } + + const QRect bounds = window()->geometry(); + const SIZE size = { bounds.width(), bounds.height() }; + const POINT ptDst = { bounds.x(), bounds.y() }; + const POINT ptSrc = { 0, 0 }; + const BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255.0 * opacity(), AC_SRC_ALPHA }; + const QRect r = region.boundingRect(); + const RECT dirty = { r.left(), r.top(), r.left() + r.width(), r.top() + r.height() }; + UPDATELAYEREDWINDOWINFO info = { sizeof(UPDATELAYEREDWINDOWINFO), NULL, + &ptDst, &size, hdc, &ptSrc, 0, &blend, ULW_ALPHA, &dirty }; + if (!UpdateLayeredWindowIndirect(handle(), &info)) + qErrnoWarning(GetLastError(), "Failed to update the layered window"); + + hr = dxgiSurface->ReleaseDC(NULL); + if (FAILED(hr)) + qErrnoWarning(hr, "Failed to release the DC for presentation"); +} + +void QWindowsDirect2DWindow::setupSwapChain() +{ DXGI_SWAP_CHAIN_DESC1 desc = {}; desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; @@ -77,72 +202,7 @@ QWindowsDirect2DWindow::QWindowsDirect2DWindow(QWindow *window, const QWindowsWi if (FAILED(hr)) qWarning("%s: Could not create swap chain: %#x", __FUNCTION__, hr); - hr = QWindowsDirect2DContext::instance()->d2dDevice()->CreateDeviceContext( - D2D1_DEVICE_CONTEXT_OPTIONS_NONE, - m_deviceContext.GetAddressOf()); - if (FAILED(hr)) - qWarning("%s: Couldn't create Direct2D Device context: %#x", __FUNCTION__, hr); -} - -QWindowsDirect2DWindow::~QWindowsDirect2DWindow() -{ -} - -QPixmap *QWindowsDirect2DWindow::pixmap() -{ - setupBitmap(); - - return m_pixmap.data(); -} - -void QWindowsDirect2DWindow::flush(QWindowsDirect2DBitmap *bitmap, const QRegion ®ion, const QPoint &offset) -{ - DXGI_SWAP_CHAIN_DESC1 desc; - HRESULT hr = m_swapChain->GetDesc1(&desc); - QRect geom = geometry(); - - if (FAILED(hr) || (desc.Width != geom.width()) || (desc.Height != geom.height())) { - resizeSwapChain(geom.size()); - m_swapChain->GetDesc1(&desc); - } - - setupBitmap(); - if (!m_bitmap) - return; - - if (bitmap != m_bitmap.data()) { - m_bitmap->deviceContext()->begin(); - - ID2D1DeviceContext *dc = m_bitmap->deviceContext()->get(); - if (!m_needsFullFlush) { - QRegion clipped = region; - clipped &= QRect(0, 0, desc.Width, desc.Height); - - foreach (const QRect &rect, clipped.rects()) { - QRectF rectF(rect); - dc->DrawBitmap(bitmap->bitmap(), - to_d2d_rect_f(rectF), - 1.0, - D2D1_INTERPOLATION_MODE_LINEAR, - to_d2d_rect_f(rectF.translated(offset.x(), offset.y()))); - } - } else { - QRectF rectF(0, 0, desc.Width, desc.Height); - dc->DrawBitmap(bitmap->bitmap(), - to_d2d_rect_f(rectF), - 1.0, - D2D1_INTERPOLATION_MODE_LINEAR, - to_d2d_rect_f(rectF.translated(offset.x(), offset.y()))); - m_needsFullFlush = false; - } - - m_bitmap->deviceContext()->end(); - } -} - -void QWindowsDirect2DWindow::present() -{ - m_swapChain->Present(0, 0); + m_needsFullFlush = true; } void QWindowsDirect2DWindow::resizeSwapChain(const QSize &size) @@ -209,14 +269,34 @@ void QWindowsDirect2DWindow::setupBitmap() if (!m_deviceContext) return; - if (!m_swapChain) + if (m_directRendering && !m_swapChain) return; + HRESULT hr; ComPtr backBufferSurface; - HRESULT hr = m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBufferSurface)); - if (FAILED(hr)) { - qWarning("%s: Could not query backbuffer for DXGI Surface: %#x", __FUNCTION__, hr); - return; + if (m_directRendering) { + hr = m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBufferSurface)); + if (FAILED(hr)) { + qWarning("%s: Could not query backbuffer for DXGI Surface: %#x", __FUNCTION__, hr); + return; + } + } else { + const QRect rect = geometry(); + CD3D11_TEXTURE2D_DESC backBufferDesc(DXGI_FORMAT_B8G8R8A8_UNORM, rect.width(), rect.height(), 1, 1); + backBufferDesc.BindFlags = D3D11_BIND_RENDER_TARGET; + backBufferDesc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE; + ComPtr backBufferTexture; + HRESULT hr = QWindowsDirect2DContext::instance()->d3dDevice()->CreateTexture2D(&backBufferDesc, NULL, &backBufferTexture); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to create backing texture for indirect rendering"); + return; + } + + hr = backBufferTexture.As(&backBufferSurface); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to cast back buffer surface to DXGI surface"); + return; + } } ComPtr backBufferBitmap; diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h index 47c790da5d..6835c9cf6f 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h @@ -56,9 +56,12 @@ public: QWindowsDirect2DWindow(QWindow *window, const QWindowsWindowData &data); ~QWindowsDirect2DWindow(); + void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE; + QPixmap *pixmap(); void flush(QWindowsDirect2DBitmap *bitmap, const QRegion ®ion, const QPoint &offset); - void present(); + void present(const QRegion ®ion); + void setupSwapChain(); void resizeSwapChain(const QSize &size); QSharedPointer copyBackBuffer() const; @@ -72,6 +75,7 @@ private: QScopedPointer m_bitmap; QScopedPointer m_pixmap; bool m_needsFullFlush; + bool m_directRendering; }; QT_END_NAMESPACE From 97a32c8440919cc22ab8d9178c3bba09b05fb721 Mon Sep 17 00:00:00 2001 From: Maks Naumov Date: Mon, 1 Sep 2014 20:34:53 +0300 Subject: [PATCH 10/89] Fix radioButton height for Windows style Change-Id: I755ed32f7458fec0fcbc5243d25fb1f6ecf46492 Task-number: QTBUG-32420 Reviewed-by: Pierre Rossi --- src/widgets/styles/qwindowsstyle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index 9ab8f8f08a..cf0afd8031 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -909,7 +909,7 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, int xOffset = 0; int yOffset = 0; int indicatorWidth = proxy()->pixelMetric(PM_ExclusiveIndicatorWidth); - int indicatorHeight = proxy()->pixelMetric(PM_ExclusiveIndicatorWidth); + int indicatorHeight = proxy()->pixelMetric(PM_ExclusiveIndicatorHeight); if (ir.width() > indicatorWidth) xOffset += (ir.width() - indicatorWidth)/2; if (ir.height() > indicatorHeight) From de068472f1368450bad4aff74eec0bc112ae413a Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 22 Aug 2014 21:13:40 +0200 Subject: [PATCH 11/89] QIconLoader: enable an easy case of transactional processing It's easy to do the work on the side and then commit. This is strongly exception safe, but in Qt, we don't care. But transactional code, when this easy to achieve, is also clearer. Change-Id: I30f1badec7745d62a09af4eede234cb312b373aa Reviewed-by: Friedemann Kleint --- src/gui/image/qiconloader.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index 12d9f9f14d..44935333fc 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -561,15 +561,16 @@ void QIconLoaderEngine::virtual_hook(int id, void *data) { QIconEngine::AvailableSizesArgument &arg = *reinterpret_cast(data); - arg.sizes.clear(); const int N = m_entries.size(); - arg.sizes.reserve(N); + QList sizes; + sizes.reserve(N); // Gets all sizes from the DirectoryInfo entries for (int i = 0; i < N; ++i) { int size = m_entries.at(i)->dir.size; - arg.sizes.append(QSize(size, size)); + sizes.append(QSize(size, size)); } + arg.sizes.swap(sizes); // commit } break; case QIconEngine::IconNameHook: From 09754d218a9c8f19f9a8f9bf920bc52064163d7a Mon Sep 17 00:00:00 2001 From: Maks Naumov Date: Tue, 2 Sep 2014 00:50:21 +0300 Subject: [PATCH 12/89] QTextEngine: remove unnecessary assignment in LayoutData::reallocate() Change-Id: I82e34d5525354fc20ca9aba6df3767e3fee51bf8 Reviewed-by: Lars Knoll --- src/gui/text/qtextengine.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 17bc4fde98..2db8b3fc1b 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -2385,8 +2385,7 @@ bool QTextEngine::LayoutData::reallocate(int totalGlyphs) return false; } - void **newMem = memory; - newMem = (void **)::realloc(memory_on_stack ? 0 : memory, newAllocated*sizeof(void *)); + void **newMem = (void **)::realloc(memory_on_stack ? 0 : memory, newAllocated*sizeof(void *)); if (!newMem) { layoutState = LayoutFailed; return false; From b366d0d0166bbb114ccf9a8e8be7d3c6c45e313e Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 27 Aug 2014 10:11:22 +0200 Subject: [PATCH 13/89] Make the EGL platform cursor reset the array buffer Otherwise bad things happen if the application leaves a buffer bound. [ChangeLog] The eglfs mouse cursor properly resets the array buffer to prevent rendering issues. This, just like with vertex attributes and textures, requires applications to be aware of such state changes in swapBuffers(). Change-Id: I8b383cc867d8d0d0572773eacfa650e7b33b9680 Reviewed-by: Gunnar Sletta --- src/platformsupport/eglconvenience/qeglplatformcursor.cpp | 3 +++ src/platformsupport/eglconvenience/qeglplatformcursor_p.h | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor.cpp b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp index b6293e60ec..7198d7c6fb 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcursor.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp @@ -343,6 +343,8 @@ void QEGLPlatformCursor::draw(const QRectF &r) { if (!m_program) { // one time initialization + initializeOpenGLFunctions(); + createShaderPrograms(); if (!m_cursorAtlas.texture) { @@ -387,6 +389,7 @@ void QEGLPlatformCursor::draw(const QRectF &r) }; glBindTexture(GL_TEXTURE_2D, m_cursor.texture); + glBindBuffer(GL_ARRAY_BUFFER, 0); m_program->enableAttributeArray(m_vertexCoordEntry); m_program->enableAttributeArray(m_textureCoordEntry); diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor_p.h b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h index 6f4216874a..440bcc40eb 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcursor_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h @@ -44,6 +44,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -86,7 +87,7 @@ private: bool m_active; }; -class QEGLPlatformCursor : public QPlatformCursor +class QEGLPlatformCursor : public QPlatformCursor, protected QOpenGLFunctions { public: QEGLPlatformCursor(QPlatformScreen *screen); @@ -113,7 +114,7 @@ private: void draw(const QRectF &rect); void update(const QRegion ®ion); void createShaderPrograms(); - static void createCursorTexture(uint *texture, const QImage &image); + void createCursorTexture(uint *texture, const QImage &image); void initCursorAtlas(); // current cursor information From 31938846aec24970e4a53771db201a7f0ac9ac3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeremy=20Lain=C3=A9?= Date: Tue, 2 Sep 2014 09:34:11 +0200 Subject: [PATCH 14/89] qasn1element: add QAsn1Element::toInteger This change adds the ability to decode ASN.1 INTEGER fields, provided they represent a positive number of less than 64-bit. This is needed for PKCS#12 decoding. Change-Id: Iafb76f22383278d6773b9e879a8f3ef43c8d2c8f Reviewed-by: Oliver Wolff --- src/network/ssl/qasn1element.cpp | 24 +++++++++++++++++++ src/network/ssl/qasn1element_p.h | 1 + .../ssl/qasn1element/tst_qasn1element.cpp | 8 +++++++ 3 files changed, 33 insertions(+) diff --git a/src/network/ssl/qasn1element.cpp b/src/network/ssl/qasn1element.cpp index d282a02827..cd8ebed501 100644 --- a/src/network/ssl/qasn1element.cpp +++ b/src/network/ssl/qasn1element.cpp @@ -242,6 +242,30 @@ QMultiMap QAsn1Element::toInfo() const return info; } +qint64 QAsn1Element::toInteger(bool *ok) const +{ + if (mType != QAsn1Element::IntegerType || mValue.isEmpty()) { + if (ok) + *ok = false; + return 0; + } + + // NOTE: negative numbers are not handled + if (mValue.at(0) & 0x80) { + if (ok) + *ok = false; + return 0; + } + + qint64 value = mValue.at(0) & 0x7f; + for (int i = 1; i < mValue.size(); ++i) + value = (value << 8) | quint8(mValue.at(i)); + + if (ok) + *ok = true; + return value; +} + QVector QAsn1Element::toVector() const { QVector items; diff --git a/src/network/ssl/qasn1element_p.h b/src/network/ssl/qasn1element_p.h index 6b3179ac35..949fd69875 100644 --- a/src/network/ssl/qasn1element_p.h +++ b/src/network/ssl/qasn1element_p.h @@ -97,6 +97,7 @@ public: QDateTime toDateTime() const; QMultiMap toInfo() const; + qint64 toInteger(bool *ok = 0) const; QVector toVector() const; QByteArray toObjectId() const; QByteArray toObjectName() const; diff --git a/tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp b/tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp index 661d13bc69..5fb4c28282 100644 --- a/tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp +++ b/tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp @@ -122,6 +122,14 @@ void tst_QAsn1Element::integer() QFETCH(QByteArray, encoded); QFETCH(int, value); + // read + bool ok; + QAsn1Element elem; + QVERIFY(elem.read(encoded)); + QCOMPARE(elem.type(), quint8(QAsn1Element::IntegerType)); + QCOMPARE(elem.toInteger(&ok), value); + QVERIFY(ok); + // write QByteArray buffer; QDataStream stream(&buffer, QIODevice::WriteOnly); From 552639c3590e793023539078bd97aa8b1ba2c2d3 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 29 Aug 2014 16:53:31 +0200 Subject: [PATCH 15/89] Windows XP, Vista styles: Share dynamically resolved theme functions. Extract a struct containing the function pointers and derive QWindowsXPStylePrivate from it, so that both styles can use them. Remove duplicated variables. Task-number: QTBUG-38858 Change-Id: I7c2c665b5930c56ffdf33c5185720f71517d146c Reviewed-by: Alessandro Portale --- src/widgets/styles/qwindowsvistastyle.cpp | 148 ++++------------ src/widgets/styles/qwindowsvistastyle_p_p.h | 1 - src/widgets/styles/qwindowsxpstyle.cpp | 182 +++++++++++--------- src/widgets/styles/qwindowsxpstyle_p_p.h | 60 ++++++- 4 files changed, 190 insertions(+), 201 deletions(-) diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index e3699da7ef..672f5c78ac 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -82,66 +82,16 @@ static const int windowsRightBorder = 15; // right border on windows # define CMDLGS_DISABLED 4 #endif -// Runtime resolved theme engine function calls - - -typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); -typedef HTHEME (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList); -typedef HTHEME (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList); -typedef HRESULT (WINAPI *PtrCloseThemeData)(HTHEME hTheme); -typedef HRESULT (WINAPI *PtrDrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); -typedef HRESULT (WINAPI *PtrDrawThemeBackgroundEx)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const DTBGOPTS *pOptions); -typedef HRESULT (WINAPI *PtrGetCurrentThemeName)(OUT LPWSTR pszThemeFileName, int cchMaxNameChars, OUT OPTIONAL LPWSTR pszColorBuff, int cchMaxColorChars, OUT OPTIONAL LPWSTR pszSizeBuff, int cchMaxSizeChars); -typedef HRESULT (WINAPI *PtrGetThemeBool)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT BOOL *pfVal); -typedef HRESULT (WINAPI *PtrGetThemeColor)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT COLORREF *pColor); -typedef HRESULT (WINAPI *PtrGetThemeEnumValue)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); -typedef HRESULT (WINAPI *PtrGetThemeFilename)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszThemeFileName, int cchMaxBuffChars); -typedef HRESULT (WINAPI *PtrGetThemeFont)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT LOGFONT *pFont); -typedef HRESULT (WINAPI *PtrGetThemeInt)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); -typedef HRESULT (WINAPI *PtrGetThemeIntList)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT INTLIST *pIntList); -typedef HRESULT (WINAPI *PtrGetThemeMargins)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OPTIONAL RECT *prc, OUT MARGINS *pMargins); -typedef HRESULT (WINAPI *PtrGetThemeMetric)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT int *piVal); -typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); -typedef HRESULT (WINAPI *PtrGetThemePosition)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT POINT *pPoint); -typedef HRESULT (WINAPI *PtrGetThemeRect)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT RECT *pRect); -typedef HRESULT (WINAPI *PtrGetThemeString)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszBuff, int cchMaxBuffChars); -typedef HRESULT (WINAPI *PtrGetThemeTransitionDuration)(HTHEME hTheme, int iPartId, int iStateFromId, int iStateToId, int iPropId, int *pDuration); -typedef HRESULT (WINAPI *PtrIsThemePartDefined)(HTHEME hTheme, int iPartId, int iStateId); -typedef HRESULT (WINAPI *PtrSetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList); -typedef HRESULT (WINAPI *PtrGetThemePropertyOrigin)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT enum PROPERTYORIGIN *pOrigin); - -static PtrIsThemePartDefined pIsThemePartDefined = 0; -static PtrOpenThemeData pOpenThemeData = 0; -static PtrCloseThemeData pCloseThemeData = 0; -static PtrDrawThemeBackground pDrawThemeBackground = 0; -static PtrDrawThemeBackgroundEx pDrawThemeBackgroundEx = 0; -static PtrGetCurrentThemeName pGetCurrentThemeName = 0; -static PtrGetThemeBool pGetThemeBool = 0; -static PtrGetThemeColor pGetThemeColor = 0; -static PtrGetThemeEnumValue pGetThemeEnumValue = 0; -static PtrGetThemeFilename pGetThemeFilename = 0; -static PtrGetThemeFont pGetThemeFont = 0; -static PtrGetThemeInt pGetThemeInt = 0; -static PtrGetThemeIntList pGetThemeIntList = 0; -static PtrGetThemeMargins pGetThemeMargins = 0; -static PtrGetThemeMetric pGetThemeMetric = 0; -static PtrGetThemePartSize pGetThemePartSize = 0; -static PtrGetThemePosition pGetThemePosition = 0; -static PtrGetThemeRect pGetThemeRect = 0; -static PtrGetThemeString pGetThemeString = 0; -static PtrGetThemeTransitionDuration pGetThemeTransitionDuration= 0; -static PtrSetWindowTheme pSetWindowTheme = 0; -static PtrGetThemePropertyOrigin pGetThemePropertyOrigin = 0; - /* \internal Checks if we should use Vista style , or if we should fall back to Windows style. */ bool QWindowsVistaStylePrivate::useVista() { - return (QWindowsVistaStylePrivate::useXP() && - (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && - (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based))); + return (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA + && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)) + && QWindowsVistaStylePrivate::useXP() + && QWindowsVistaStylePrivate::pGetThemeTransitionDuration != Q_NULLPTR; } /* \internal @@ -392,7 +342,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt //translate state flags to UXTHEME states : if (element == PE_FrameLineEdit) { - theme = pOpenThemeData(0, L"Edit"); + theme = QWindowsXPStylePrivate::pOpenThemeData(0, L"Edit"); partId = EP_EDITBORDER_NOSCROLL; if (oldState & State_MouseOver) @@ -410,7 +360,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt toState = ETS_NORMAL; } else { - theme = pOpenThemeData(0, L"Button"); + theme = QWindowsXPStylePrivate::pOpenThemeData(0, L"Button"); if (element == PE_IndicatorRadioButton) partId = BP_RADIOBUTTON; else if (element == PE_IndicatorCheckBox) @@ -423,7 +373,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt } // Retrieve the transition time between the states from the system. - if (theme && pGetThemeTransitionDuration(theme, partId, fromState, toState, + if (theme && QWindowsXPStylePrivate::pGetThemeTransitionDuration(theme, partId, fromState, toState, TMT_TRANSITIONDURATIONS, &duration) == S_OK) { t->setDuration(duration); @@ -460,7 +410,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt static int decoration_size = 0; if (d->initTreeViewTheming() && theme.isValid() && !decoration_size) { SIZE size; - pGetThemePartSize(theme.handle(), 0, TVP_HOTGLYPH, GLPS_OPENED, 0, TS_TRUE, &size); + QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, TVP_HOTGLYPH, GLPS_OPENED, 0, TS_TRUE, &size); decoration_size = qMax(size.cx, size.cy); } int mid_h = option->rect.x() + option->rect.width() / 2; @@ -541,7 +491,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt EP_EDITBORDER_HVSCROLL, stateId, option->rect); // Since EP_EDITBORDER_HVSCROLL does not us borderfill, theme.noContent cannot be used for clipping int borderSize = 1; - pGetThemeInt(theme.handle(), theme.partId, theme.stateId, TMT_BORDERSIZE, &borderSize); + QWindowsXPStylePrivate::pGetThemeInt(theme.handle(), theme.partId, theme.stateId, TMT_BORDERSIZE, &borderSize); QRegion clipRegion = option->rect; QRegion content = option->rect.adjusted(borderSize, borderSize, -borderSize, -borderSize); clipRegion ^= content; @@ -593,7 +543,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt return; } int bgType; - pGetThemeEnumValue( theme.handle(), + QWindowsXPStylePrivate::pGetThemeEnumValue( theme.handle(), partId, stateId, TMT_BGTYPE, @@ -604,11 +554,11 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt QBrush fillColor = option->palette.brush(QPalette::Base); if (!isEnabled) { PROPERTYORIGIN origin = PO_NOTFOUND; - pGetThemePropertyOrigin(theme.handle(), theme.partId, theme.stateId, TMT_FILLCOLOR, &origin); + QWindowsXPStylePrivate::pGetThemePropertyOrigin(theme.handle(), theme.partId, theme.stateId, TMT_FILLCOLOR, &origin); // Use only if the fill property comes from our part if ((origin == PO_PART || origin == PO_STATE)) { COLORREF bgRef; - pGetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef); + QWindowsXPStylePrivate::pGetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef); fillColor = QBrush(qRgb(GetRValue(bgRef), GetGValue(bgRef), GetBValue(bgRef))); } } @@ -944,11 +894,11 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption int duration = 0; - HTHEME theme = pOpenThemeData(0, L"Button"); + HTHEME theme = QWindowsXPStylePrivate::pOpenThemeData(0, L"Button"); int fromState = buttonStateId(oldState, BP_PUSHBUTTON); int toState = buttonStateId(option->state, BP_PUSHBUTTON); - if (pGetThemeTransitionDuration(theme, BP_PUSHBUTTON, fromState, toState, TMT_TRANSITIONDURATIONS, &duration) == S_OK) + if (QWindowsXPStylePrivate::pGetThemeTransitionDuration(theme, BP_PUSHBUTTON, fromState, toState, TMT_TRANSITIONDURATIONS, &duration) == S_OK) t->setDuration(duration); else t->setDuration(0); @@ -1041,7 +991,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption TP_DROPDOWNBUTTON); if (theme.isValid()) { SIZE size; - if (pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) { + if (QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) { mbiw = size.cx; mbih = size.cy; } @@ -1237,8 +1187,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption MARGINS margins; XPThemeData theme(widget, 0, QWindowsXPStylePrivate::MenuTheme, MENU_POPUPCHECKBACKGROUND, MBI_HOT); - pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); - pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins); + QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); + QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins); checkcol = qMax(menuitem->maxIconWidth, int(3 + size.cx + margins.cxLeftWidth + margins.cxRightWidth)); } QRect rect = option->rect; @@ -1293,8 +1243,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption menuitem->icon.isNull() ? MBI_HOT : MBI_PUSHED, vCheckRect); SIZE size; MARGINS margins; - pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); - pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, + QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); + QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins); QRect checkRect(0, 0, size.cx + margins.cxLeftWidth + margins.cxRightWidth , size.cy + margins.cyBottomHeight + margins.cyTopHeight); @@ -1815,11 +1765,11 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle MARGINS contentsMargin; RECT rect = theme.toRECT(theme.rect); - pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin); + QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin); SIZE size; theme.partId = flags & State_Horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); int gw = size.cx, gh = size.cy; @@ -1938,8 +1888,8 @@ QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption XPThemeData theme(widget, 0, QWindowsXPStylePrivate::MenuTheme, MENU_POPUPCHECKBACKGROUND, MBI_HOT); - pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); - pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins); + QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); + QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins); minimumHeight = qMax(size.cy + margins.cyBottomHeight+ margins.cyTopHeight, sz.height()); sz.rwidth() += size.cx + margins.cxLeftWidth + margins.cxRightWidth; } @@ -2001,7 +1951,7 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption case SE_PushButtonContents: if (const QStyleOptionButton *btn = qstyleoption_cast(option)) { MARGINS borderSize; - HTHEME theme = pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"Button"); + HTHEME theme = QWindowsXPStylePrivate::pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"Button"); if (theme) { int stateId = PBS_NORMAL; if (!(option->state & State_Enabled)) @@ -2016,7 +1966,7 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption int border = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget); rect = option->rect.adjusted(border, border, -border, -border); - int result = pGetThemeMargins(theme, + int result = QWindowsXPStylePrivate::pGetThemeMargins(theme, NULL, BP_PUSHBUTTON, stateId, @@ -2050,7 +2000,7 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption int arrowHeight = 5; if (theme.isValid()) { SIZE size; - if (pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) { + if (QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) { arrowWidth = size.cx; arrowHeight = size.cy; } @@ -2382,9 +2332,9 @@ void QWindowsVistaStyle::polish(QWidget *widget) //we do not have to care about unpolishing widget->setContentsMargins(3, 0, 4, 0); COLORREF bgRef; - HTHEME theme = pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"TOOLTIP"); + HTHEME theme = QWindowsXPStylePrivate::pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"TOOLTIP"); if (theme) { - if (pGetThemeColor(theme, TTP_STANDARD, TTSS_NORMAL, TMT_TEXTCOLOR, &bgRef) == S_OK) { + if (QWindowsXPStylePrivate::pGetThemeColor(theme, TTP_STANDARD, TTSS_NORMAL, TMT_TEXTCOLOR, &bgRef) == S_OK) { QColor textColor = QColor::fromRgb(bgRef); QPalette pal; pal.setColor(QPalette::All, QPalette::ToolTipText, textColor); @@ -2492,7 +2442,6 @@ QPixmap QWindowsVistaStyle::standardPixmap(StandardPixmap standardPixmap, const QWindowsVistaStylePrivate::QWindowsVistaStylePrivate() : QWindowsXPStylePrivate(), m_treeViewHelper(0) { - resolveSymbols(); } QWindowsVistaStylePrivate::~QWindowsVistaStylePrivate() @@ -2511,43 +2460,6 @@ bool QWindowsVistaStylePrivate::transitionsEnabled() const return false; } -/*! \internal - Returns \c true if all the necessary theme engine symbols were - resolved. -*/ -bool QWindowsVistaStylePrivate::resolveSymbols() -{ - static bool tried = false; - if (!tried) { - tried = true; - QSystemLibrary themeLib(QLatin1String("uxtheme")); - pSetWindowTheme = (PtrSetWindowTheme )themeLib.resolve("SetWindowTheme"); - pIsThemePartDefined = (PtrIsThemePartDefined )themeLib.resolve("IsThemePartDefined"); - pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); - pOpenThemeData = (PtrOpenThemeData )themeLib.resolve("OpenThemeData"); - pCloseThemeData = (PtrCloseThemeData )themeLib.resolve("CloseThemeData"); - pDrawThemeBackground = (PtrDrawThemeBackground )themeLib.resolve("DrawThemeBackground"); - pDrawThemeBackgroundEx = (PtrDrawThemeBackgroundEx )themeLib.resolve("DrawThemeBackgroundEx"); - pGetCurrentThemeName = (PtrGetCurrentThemeName )themeLib.resolve("GetCurrentThemeName"); - pGetThemeBool = (PtrGetThemeBool )themeLib.resolve("GetThemeBool"); - pGetThemeColor = (PtrGetThemeColor )themeLib.resolve("GetThemeColor"); - pGetThemeEnumValue = (PtrGetThemeEnumValue )themeLib.resolve("GetThemeEnumValue"); - pGetThemeFilename = (PtrGetThemeFilename )themeLib.resolve("GetThemeFilename"); - pGetThemeFont = (PtrGetThemeFont )themeLib.resolve("GetThemeFont"); - pGetThemeInt = (PtrGetThemeInt )themeLib.resolve("GetThemeInt"); - pGetThemeIntList = (PtrGetThemeIntList )themeLib.resolve("GetThemeIntList"); - pGetThemeMargins = (PtrGetThemeMargins )themeLib.resolve("GetThemeMargins"); - pGetThemeMetric = (PtrGetThemeMetric )themeLib.resolve("GetThemeMetric"); - pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); - pGetThemePosition = (PtrGetThemePosition )themeLib.resolve("GetThemePosition"); - pGetThemeRect = (PtrGetThemeRect )themeLib.resolve("GetThemeRect"); - pGetThemeString = (PtrGetThemeString )themeLib.resolve("GetThemeString"); - pGetThemeTransitionDuration = (PtrGetThemeTransitionDuration)themeLib.resolve("GetThemeTransitionDuration"); - pGetThemePropertyOrigin = (PtrGetThemePropertyOrigin)themeLib.resolve("GetThemePropertyOrigin"); - } - return pGetThemeTransitionDuration != 0; -} - /* * We need to set the windows "explorer" theme explicitly on a native * window and open the "TREEVIEW" theme handle passing its window handle @@ -2584,7 +2496,7 @@ bool QWindowsVistaStylePrivate::initTreeViewTheming() qWarning("%s: Unable to create the treeview helper window.", Q_FUNC_INFO); return false; } - const HRESULT hr = pSetWindowTheme(m_treeViewHelper, L"explorer", NULL); + const HRESULT hr = QWindowsXPStylePrivate::pSetWindowTheme(m_treeViewHelper, L"explorer", NULL); if (hr != S_OK) { qErrnoWarning("%s: SetWindowTheme() failed.", Q_FUNC_INFO); return false; @@ -2620,7 +2532,7 @@ QIcon QWindowsVistaStyle::standardIcon(StandardPixmap standardIcon, BP_COMMANDLINKGLYPH, CMDLGS_NORMAL); if (theme.isValid()) { SIZE size; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); QIcon linkGlyph; QPixmap pm = QPixmap(size.cx, size.cy); pm.fill(Qt::transparent); diff --git a/src/widgets/styles/qwindowsvistastyle_p_p.h b/src/widgets/styles/qwindowsvistastyle_p_p.h index f2f208fbb5..a7f219db8d 100644 --- a/src/widgets/styles/qwindowsvistastyle_p_p.h +++ b/src/widgets/styles/qwindowsvistastyle_p_p.h @@ -171,7 +171,6 @@ class QWindowsVistaStylePrivate : public QWindowsXPStylePrivate public: QWindowsVistaStylePrivate(); ~QWindowsVistaStylePrivate(); - static bool resolveSymbols(); static inline bool useVista(); bool transitionsEnabled() const; diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index e694eb4e7e..2e3586db42 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -77,56 +77,76 @@ QT_BEGIN_NAMESPACE // Runtime resolved theme engine function calls -typedef bool (WINAPI *PtrIsAppThemed)(); -typedef bool (WINAPI *PtrIsThemeActive)(); -typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); -typedef HTHEME (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList); -typedef HRESULT (WINAPI *PtrCloseThemeData)(HTHEME hTheme); -typedef HRESULT (WINAPI *PtrDrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); -typedef HRESULT (WINAPI *PtrDrawThemeBackgroundEx)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const DTBGOPTS *pOptions); -typedef HRESULT (WINAPI *PtrGetCurrentThemeName)(OUT LPWSTR pszThemeFileName, int cchMaxNameChars, OUT OPTIONAL LPWSTR pszColorBuff, int cchMaxColorChars, OUT OPTIONAL LPWSTR pszSizeBuff, int cchMaxSizeChars); -typedef HRESULT (WINAPI *PtrGetThemeDocumentationProperty)(LPCWSTR pszThemeName, LPCWSTR pszPropertyName, OUT LPWSTR pszValueBuff, int cchMaxValChars); -typedef HRESULT (WINAPI *PtrGetThemeBool)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT BOOL *pfVal); -typedef HRESULT (WINAPI *PtrGetThemeColor)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT COLORREF *pColor); -typedef HRESULT (WINAPI *PtrGetThemeEnumValue)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); -typedef HRESULT (WINAPI *PtrGetThemeFilename)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszThemeFileName, int cchMaxBuffChars); -typedef HRESULT (WINAPI *PtrGetThemeFont)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT LOGFONT *pFont); -typedef HRESULT (WINAPI *PtrGetThemeInt)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); -typedef HRESULT (WINAPI *PtrGetThemeIntList)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT INTLIST *pIntList); -typedef HRESULT (WINAPI *PtrGetThemeMargins)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OPTIONAL RECT *prc, OUT MARGINS *pMargins); -typedef HRESULT (WINAPI *PtrGetThemeMetric)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT int *piVal); -typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); -typedef HRESULT (WINAPI *PtrGetThemePosition)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT POINT *pPoint); -typedef HRESULT (WINAPI *PtrGetThemePropertyOrigin)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT enum PROPERTYORIGIN *pOrigin); -typedef HRESULT (WINAPI *PtrGetThemeRect)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT RECT *pRect); -typedef HRESULT (WINAPI *PtrGetThemeString)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszBuff, int cchMaxBuffChars); -typedef HRESULT (WINAPI *PtrGetThemeBackgroundRegion)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, const RECT *pRect, OUT HRGN *pRegion); -typedef BOOL (WINAPI *PtrIsThemeBackgroundPartiallyTransparent)(HTHEME hTheme, int iPartId, int iStateId); -static PtrIsAppThemed pIsAppThemed = 0; -static PtrIsThemeActive pIsThemeActive = 0; -static PtrOpenThemeData pOpenThemeData = 0; -static PtrCloseThemeData pCloseThemeData = 0; -static PtrDrawThemeBackground pDrawThemeBackground = 0; -static PtrDrawThemeBackgroundEx pDrawThemeBackgroundEx = 0; -static PtrGetCurrentThemeName pGetCurrentThemeName = 0; -static PtrGetThemeBool pGetThemeBool = 0; -static PtrGetThemeColor pGetThemeColor = 0; -static PtrGetThemeEnumValue pGetThemeEnumValue = 0; -static PtrGetThemeFilename pGetThemeFilename = 0; -static PtrGetThemeFont pGetThemeFont = 0; -static PtrGetThemeInt pGetThemeInt = 0; -static PtrGetThemeIntList pGetThemeIntList = 0; -static PtrGetThemeMargins pGetThemeMargins = 0; -static PtrGetThemeMetric pGetThemeMetric = 0; -static PtrGetThemePartSize pGetThemePartSize = 0; -static PtrGetThemePosition pGetThemePosition = 0; -static PtrGetThemePropertyOrigin pGetThemePropertyOrigin = 0; -static PtrGetThemeRect pGetThemeRect = 0; -static PtrGetThemeString pGetThemeString = 0; -static PtrGetThemeBackgroundRegion pGetThemeBackgroundRegion = 0; -static PtrGetThemeDocumentationProperty pGetThemeDocumentationProperty = 0; -static PtrIsThemeBackgroundPartiallyTransparent pIsThemeBackgroundPartiallyTransparent = 0; +QWindowsUxThemeLib::PtrIsAppThemed QWindowsUxThemeLib::pIsAppThemed = Q_NULLPTR; +QWindowsUxThemeLib::PtrIsThemeActive QWindowsUxThemeLib::pIsThemeActive = Q_NULLPTR; +QWindowsUxThemeLib::PtrOpenThemeData QWindowsUxThemeLib::pOpenThemeData = Q_NULLPTR; +QWindowsUxThemeLib::PtrCloseThemeData QWindowsUxThemeLib::pCloseThemeData = Q_NULLPTR; +QWindowsUxThemeLib::PtrDrawThemeBackground QWindowsUxThemeLib::pDrawThemeBackground = Q_NULLPTR; +QWindowsUxThemeLib::PtrDrawThemeBackgroundEx QWindowsUxThemeLib::pDrawThemeBackgroundEx = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetCurrentThemeName QWindowsUxThemeLib::pGetCurrentThemeName = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeBool QWindowsUxThemeLib::pGetThemeBool = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeColor QWindowsUxThemeLib::pGetThemeColor = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeEnumValue QWindowsUxThemeLib::pGetThemeEnumValue = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeFilename QWindowsUxThemeLib::pGetThemeFilename = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeFont QWindowsUxThemeLib::pGetThemeFont = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeInt QWindowsUxThemeLib::pGetThemeInt = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeIntList QWindowsUxThemeLib::pGetThemeIntList = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeMargins QWindowsUxThemeLib::pGetThemeMargins = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeMetric QWindowsUxThemeLib::pGetThemeMetric = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemePartSize QWindowsUxThemeLib::pGetThemePartSize = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemePosition QWindowsUxThemeLib::pGetThemePosition = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemePropertyOrigin QWindowsUxThemeLib::pGetThemePropertyOrigin = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeRect QWindowsUxThemeLib::pGetThemeRect = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeString QWindowsUxThemeLib::pGetThemeString = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeBackgroundRegion QWindowsUxThemeLib::pGetThemeBackgroundRegion = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeDocumentationProperty QWindowsUxThemeLib::pGetThemeDocumentationProperty = Q_NULLPTR; +QWindowsUxThemeLib::PtrIsThemeBackgroundPartiallyTransparent + QWindowsUxThemeLib::pIsThemeBackgroundPartiallyTransparent = Q_NULLPTR; +QWindowsUxThemeLib::PtrSetWindowTheme QWindowsUxThemeLib::pSetWindowTheme = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeTransitionDuration QWindowsUxThemeLib::pGetThemeTransitionDuration = Q_NULLPTR; + +bool QWindowsUxThemeLib::resolveSymbols() +{ + static bool tried = false; + if (tried) + return pIsAppThemed != Q_NULLPTR; + tried = true; + QSystemLibrary themeLib(QLatin1String("uxtheme")); + if (!themeLib.load()) + return false; + pIsAppThemed = (PtrIsAppThemed)themeLib.resolve("IsAppThemed"); + if (!pIsAppThemed) + return false; + pIsThemeActive = (PtrIsThemeActive )themeLib.resolve("IsThemeActive"); + pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); + pOpenThemeData = (PtrOpenThemeData )themeLib.resolve("OpenThemeData"); + pCloseThemeData = (PtrCloseThemeData )themeLib.resolve("CloseThemeData"); + pDrawThemeBackground = (PtrDrawThemeBackground )themeLib.resolve("DrawThemeBackground"); + pDrawThemeBackgroundEx = (PtrDrawThemeBackgroundEx )themeLib.resolve("DrawThemeBackgroundEx"); + pGetCurrentThemeName = (PtrGetCurrentThemeName )themeLib.resolve("GetCurrentThemeName"); + pGetThemeBool = (PtrGetThemeBool )themeLib.resolve("GetThemeBool"); + pGetThemeColor = (PtrGetThemeColor )themeLib.resolve("GetThemeColor"); + pGetThemeEnumValue = (PtrGetThemeEnumValue )themeLib.resolve("GetThemeEnumValue"); + pGetThemeFilename = (PtrGetThemeFilename )themeLib.resolve("GetThemeFilename"); + pGetThemeFont = (PtrGetThemeFont )themeLib.resolve("GetThemeFont"); + pGetThemeInt = (PtrGetThemeInt )themeLib.resolve("GetThemeInt"); + pGetThemeIntList = (PtrGetThemeIntList )themeLib.resolve("GetThemeIntList"); + pGetThemeMargins = (PtrGetThemeMargins )themeLib.resolve("GetThemeMargins"); + pGetThemeMetric = (PtrGetThemeMetric )themeLib.resolve("GetThemeMetric"); + pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); + pGetThemePosition = (PtrGetThemePosition )themeLib.resolve("GetThemePosition"); + pGetThemePropertyOrigin = (PtrGetThemePropertyOrigin)themeLib.resolve("GetThemePropertyOrigin"); + pGetThemeRect = (PtrGetThemeRect )themeLib.resolve("GetThemeRect"); + pGetThemeString = (PtrGetThemeString )themeLib.resolve("GetThemeString"); + pGetThemeBackgroundRegion = (PtrGetThemeBackgroundRegion )themeLib.resolve("GetThemeBackgroundRegion"); + pGetThemeDocumentationProperty = (PtrGetThemeDocumentationProperty )themeLib.resolve("GetThemeDocumentationProperty"); + pIsThemeBackgroundPartiallyTransparent = (PtrIsThemeBackgroundPartiallyTransparent)themeLib.resolve("IsThemeBackgroundPartiallyTransparent"); + pSetWindowTheme = (PtrSetWindowTheme )themeLib.resolve("SetWindowTheme"); + if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA) + pGetThemeTransitionDuration = (PtrGetThemeTransitionDuration)themeLib.resolve("GetThemeTransitionDuration"); + return true; +} // General const values static const int windowsItemFrame = 2; // menu item frame width @@ -211,7 +231,7 @@ RECT XPThemeData::toRECT(const QRect &qr) */ HRGN XPThemeData::mask(QWidget *widget) { - if (!pIsThemeBackgroundPartiallyTransparent(handle(), partId, stateId)) + if (!QWindowsXPStylePrivate::pIsThemeBackgroundPartiallyTransparent(handle(), partId, stateId)) return 0; HRGN hrgn; @@ -219,7 +239,7 @@ HRGN XPThemeData::mask(QWidget *widget) if (widget) dc = hdcForWidgetBackingStore(widget); RECT nativeRect = toRECT(rect); - pGetThemeBackgroundRegion(handle(), dc, partId, stateId, &nativeRect, &hrgn); + QWindowsXPStylePrivate::pGetThemeBackgroundRegion(handle(), dc, partId, stateId, &nativeRect, &hrgn); return hrgn; } @@ -264,7 +284,7 @@ bool QWindowsXPStylePrivate::useXP(bool update) { if (!update) return use_xp; - return (use_xp = resolveSymbols() && pIsThemeActive() + return (use_xp = QWindowsUxThemeLib::resolveSymbols() && pIsThemeActive() && (pIsAppThemed() || !QApplication::instance())); } @@ -1213,9 +1233,9 @@ void QWindowsXPStyle::polish(QWidget *widget) // Get text color for group box labels COLORREF cref; XPThemeData theme(0, 0, QWindowsXPStylePrivate::ButtonTheme, 0, 0); - pGetThemeColor(theme.handle(), BP_GROUPBOX, GBS_NORMAL, TMT_TEXTCOLOR, &cref); + QWindowsXPStylePrivate::pGetThemeColor(theme.handle(), BP_GROUPBOX, GBS_NORMAL, TMT_TEXTCOLOR, &cref); d->groupBoxTextColor = qRgb(GetRValue(cref), GetGValue(cref), GetBValue(cref)); - pGetThemeColor(theme.handle(), BP_GROUPBOX, GBS_DISABLED, TMT_TEXTCOLOR, &cref); + QWindowsXPStylePrivate::pGetThemeColor(theme.handle(), BP_GROUPBOX, GBS_DISABLED, TMT_TEXTCOLOR, &cref); d->groupBoxTextColorDisabled = qRgb(GetRValue(cref), GetGValue(cref), GetBValue(cref)); // Where does this color come from? //pGetThemeColor(theme.handle(), TKP_TICS, TSS_NORMAL, TMT_COLOR, &cref); @@ -1340,7 +1360,7 @@ QRect QWindowsXPStyle::subElementRect(SubElement sr, const QStyleOption *option, int border = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget); rect = option->rect.adjusted(border, border, -border, -border); - int result = pGetThemeMargins(theme, + int result = QWindowsXPStylePrivate::pGetThemeMargins(theme, NULL, BP_PUSHBUTTON, stateId, @@ -1535,10 +1555,10 @@ case PE_Frame: else stateId = ETS_NORMAL; int fillType; - if (pGetThemeEnumValue(theme.handle(), partId, stateId, TMT_BGTYPE, &fillType) == S_OK) { + if (QWindowsXPStylePrivate::pGetThemeEnumValue(theme.handle(), partId, stateId, TMT_BGTYPE, &fillType) == S_OK) { if (fillType == BT_BORDERFILL) { COLORREF bcRef; - pGetThemeColor(theme.handle(), partId, stateId, TMT_BORDERCOLOR, &bcRef); + QWindowsXPStylePrivate::pGetThemeColor(theme.handle(), partId, stateId, TMT_BORDERCOLOR, &bcRef); QColor bordercolor(qRgb(GetRValue(bcRef), GetGValue(bcRef), GetBValue(bcRef))); QPen oldPen = p->pen(); // int borderSize = 1; @@ -1619,7 +1639,7 @@ case PE_Frame: return; } int bgType; - pGetThemeEnumValue( theme.handle(), + QWindowsXPStylePrivate::pGetThemeEnumValue( theme.handle(), partId, stateId, TMT_BGTYPE, @@ -1636,11 +1656,11 @@ case PE_Frame: if (!isEnabled) { PROPERTYORIGIN origin = PO_NOTFOUND; - pGetThemePropertyOrigin(theme.handle(), theme.partId, theme.stateId, TMT_FILLCOLOR, &origin); + QWindowsXPStylePrivate::pGetThemePropertyOrigin(theme.handle(), theme.partId, theme.stateId, TMT_FILLCOLOR, &origin); // Use only if the fill property comes from our part if ((origin == PO_PART || origin == PO_STATE)) { COLORREF bgRef; - pGetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef); + QWindowsXPStylePrivate::pGetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef); fillColor = QBrush(qRgb(GetRValue(bgRef), GetGValue(bgRef), GetBValue(bgRef))); } } @@ -1666,7 +1686,7 @@ case PE_Frame: wchar_t themeFileName[maxlength]; wchar_t themeColor[maxlength]; // Due to a a scaling issue with the XP Silver theme, tab gradients are not used with it - if (pGetCurrentThemeName(themeFileName, maxlength, themeColor, maxlength, NULL, 0) == S_OK) { + if (QWindowsXPStylePrivate::pGetCurrentThemeName(themeFileName, maxlength, themeColor, maxlength, NULL, 0) == S_OK) { wchar_t *offset = 0; if ((offset = wcsrchr(themeFileName, QChar(QLatin1Char('\\')).unicode())) != NULL) { offset++; @@ -1984,7 +2004,7 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op partId = SP_GRIPPER; SIZE sz; XPThemeData theme(0, p, themeNumber, partId, 0); - pGetThemePartSize(theme.handle(), 0, partId, 0, 0, TS_TRUE, &sz); + QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, partId, 0, 0, TS_TRUE, &sz); --sz.cy; if (const QStyleOptionSizeGrip *sg = qstyleoption_cast(option)) { switch (sg->corner) { @@ -2056,7 +2076,7 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op TP_SPLITBUTTONDROPDOWN); if (theme.isValid()) { SIZE size; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); mbiw = size.cx; mbih = size.cy; } @@ -2450,10 +2470,10 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, titleRect.width()); int result = TST_NONE; - pGetThemeEnumValue(theme.handle(), WP_SMALLCAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result); + QWindowsXPStylePrivate::pGetThemeEnumValue(theme.handle(), WP_SMALLCAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result); if (result != TST_NONE) { COLORREF textShadowRef; - pGetThemeColor(theme.handle(), WP_SMALLCAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWCOLOR, &textShadowRef); + QWindowsXPStylePrivate::pGetThemeColor(theme.handle(), WP_SMALLCAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWCOLOR, &textShadowRef); QColor textShadow = qRgb(GetRValue(textShadowRef), GetGValue(textShadowRef), GetBValue(textShadowRef)); p->setPen(textShadow); drawItemText(p, titleRect.adjusted(1, 1, 1, 1), @@ -2752,11 +2772,11 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo MARGINS contentsMargin; RECT rect = theme.toRECT(theme.rect); - pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin); + QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin); SIZE size; theme.partId = flags & State_Horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); int gw = size.cx, gh = size.cy; @@ -3062,10 +3082,10 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo QRect ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, widget); int result = TST_NONE; - pGetThemeEnumValue(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result); + QWindowsXPStylePrivate::pGetThemeEnumValue(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result); if (result != TST_NONE) { COLORREF textShadowRef; - pGetThemeColor(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWCOLOR, &textShadowRef); + QWindowsXPStylePrivate::pGetThemeColor(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWCOLOR, &textShadowRef); QColor textShadow = qRgb(GetRValue(textShadowRef), GetGValue(textShadowRef), GetBValue(textShadowRef)); p->setPen(textShadow); p->drawText(ir.x() + 3, ir.y() + 2, ir.width() - 1, ir.height(), @@ -3094,7 +3114,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo theme.partId = partId; theme.stateId = stateId; SIZE sz; - pGetThemePartSize(theme.handle(), qt_win_display_dc(), theme.partId, theme.stateId, 0, TS_TRUE, &sz); + QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), qt_win_display_dc(), theme.partId, theme.stateId, 0, TS_TRUE, &sz); if (sz.cx == 0 || sz.cy == 0) { int iconSize = proxy()->pixelMetric(PM_SmallIconSize, tb, widget); QPixmap pm = proxy()->standardIcon(SP_TitleBarMenuButton, tb, widget).pixmap(iconSize, iconSize); @@ -3372,7 +3392,7 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_CHECKBOX, CBS_UNCHECKEDNORMAL); if (theme.isValid()) { SIZE size; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); res = (pm == PM_IndicatorWidth) ? size.cx : size.cy; } } @@ -3384,7 +3404,7 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL); if (theme.isValid()) { SIZE size; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); res = (pm == PM_ExclusiveIndicatorWidth) ? size.cx : size.cy; } } @@ -3399,7 +3419,7 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con (orient == Qt::Horizontal) ? PP_CHUNK : PP_CHUNKVERT); if (theme.isValid()) { SIZE size; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); res = (orient == Qt::Horizontal) ? size.cx : size.cy; } } @@ -3411,7 +3431,7 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con TKP_THUMB); if (theme.isValid()) { SIZE size; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); res = size.cy; } } @@ -3431,7 +3451,7 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_FRAMELEFT, FS_ACTIVE); if (theme.isValid()) { SIZE size; - pGetThemePartSize(theme.handle(), 0, WP_FRAMELEFT, FS_ACTIVE, 0, TS_TRUE, &size); + QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, WP_FRAMELEFT, FS_ACTIVE, 0, TS_TRUE, &size); res = size.cx-1; } } @@ -3452,7 +3472,7 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLFRAMERIGHT, FS_ACTIVE); if (theme.isValid()) { SIZE size; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); res = size.cx; } } @@ -3750,7 +3770,7 @@ QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt HTHEME theme = buttontheme.handle(); MARGINS borderSize; if (theme) { - int result = pGetThemeMargins(theme, + int result = QWindowsXPStylePrivate::pGetThemeMargins(theme, NULL, BP_PUSHBUTTON, PBS_NORMAL, @@ -3930,7 +3950,7 @@ QPixmap QWindowsXPStyle::standardPixmap(StandardPixmap standardPixmap, const QSt XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL); if (theme.isValid()) { SIZE sz; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &sz); + QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &sz); return QIcon(QWindowsStyle::standardPixmap(standardPixmap, option, widget)).pixmap(QSize(sz.cx, sz.cy)); } } @@ -3965,7 +3985,7 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, WP_MAXBUTTON, MAXBS_NORMAL); if (theme.isValid()) { SIZE size; - pGetThemePartSize(themeSize.handle(), 0, themeSize.partId, themeSize.stateId, 0, TS_TRUE, &size); + QWindowsXPStylePrivate::pGetThemePartSize(themeSize.handle(), 0, themeSize.partId, themeSize.stateId, 0, TS_TRUE, &size); QPixmap pm = QPixmap(size.cx, size.cy); pm.fill(Qt::transparent); QPainter p(&pm); @@ -4000,7 +4020,7 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, WP_SMALLCLOSEBUTTON, CBS_NORMAL); if (theme.isValid()) { SIZE size; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); QPixmap pm = QPixmap(size.cx, size.cy); pm.fill(Qt::transparent); QPainter p(&pm); @@ -4037,7 +4057,7 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, WP_RESTOREBUTTON, RBS_NORMAL); if (theme.isValid()) { SIZE size; - pGetThemePartSize(themeSize.handle(), 0, themeSize.partId, themeSize.stateId, 0, TS_TRUE, &size); + QWindowsXPStylePrivate::pGetThemePartSize(themeSize.handle(), 0, themeSize.partId, themeSize.stateId, 0, TS_TRUE, &size); QPixmap pm = QPixmap(size.cx, size.cy); pm.fill(Qt::transparent); QPainter p(&pm); diff --git a/src/widgets/styles/qwindowsxpstyle_p_p.h b/src/widgets/styles/qwindowsxpstyle_p_p.h index 7327fa5581..190055b24b 100644 --- a/src/widgets/styles/qwindowsxpstyle_p_p.h +++ b/src/widgets/styles/qwindowsxpstyle_p_p.h @@ -282,7 +282,65 @@ struct ThemeMapData { hasAlphaChannel(false), wasAlphaSwapped(false), hadInvalidAlpha(false) {} }; -class QWindowsXPStylePrivate : public QWindowsStylePrivate +struct QWindowsUxThemeLib { + typedef bool (WINAPI *PtrIsAppThemed)(); + typedef bool (WINAPI *PtrIsThemeActive)(); + typedef HTHEME (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList); + typedef HRESULT (WINAPI *PtrCloseThemeData)(HTHEME hTheme); + typedef HRESULT (WINAPI *PtrDrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); + typedef HRESULT (WINAPI *PtrDrawThemeBackgroundEx)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const DTBGOPTS *pOptions); + typedef HRESULT (WINAPI *PtrGetCurrentThemeName)(OUT LPWSTR pszThemeFileName, int cchMaxNameChars, OUT OPTIONAL LPWSTR pszColorBuff, int cchMaxColorChars, OUT OPTIONAL LPWSTR pszSizeBuff, int cchMaxSizeChars); + typedef HRESULT (WINAPI *PtrGetThemeDocumentationProperty)(LPCWSTR pszThemeName, LPCWSTR pszPropertyName, OUT LPWSTR pszValueBuff, int cchMaxValChars); + typedef HRESULT (WINAPI *PtrGetThemeBool)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT BOOL *pfVal); + typedef HRESULT (WINAPI *PtrGetThemeColor)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT COLORREF *pColor); + typedef HRESULT (WINAPI *PtrGetThemeEnumValue)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); + typedef HRESULT (WINAPI *PtrGetThemeFilename)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszThemeFileName, int cchMaxBuffChars); + typedef HRESULT (WINAPI *PtrGetThemeFont)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT LOGFONT *pFont); + typedef HRESULT (WINAPI *PtrGetThemeInt)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); + typedef HRESULT (WINAPI *PtrGetThemeIntList)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT INTLIST *pIntList); + typedef HRESULT (WINAPI *PtrGetThemeMargins)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OPTIONAL RECT *prc, OUT MARGINS *pMargins); + typedef HRESULT (WINAPI *PtrGetThemeMetric)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT int *piVal); + typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); + typedef HRESULT (WINAPI *PtrGetThemePosition)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT POINT *pPoint); + typedef HRESULT (WINAPI *PtrGetThemePropertyOrigin)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT enum PROPERTYORIGIN *pOrigin); + typedef HRESULT (WINAPI *PtrGetThemeRect)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT RECT *pRect); + typedef HRESULT (WINAPI *PtrGetThemeString)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszBuff, int cchMaxBuffChars); + typedef HRESULT (WINAPI *PtrGetThemeBackgroundRegion)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, const RECT *pRect, OUT HRGN *pRegion); + typedef BOOL (WINAPI *PtrIsThemeBackgroundPartiallyTransparent)(HTHEME hTheme, int iPartId, int iStateId); + typedef HRESULT (WINAPI *PtrSetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList); + typedef HRESULT (WINAPI *PtrGetThemeTransitionDuration)(HTHEME hTheme, int iPartId, int iStateFromId, int iStateToId, int iPropId, int *pDuration); + + static bool resolveSymbols(); + + static PtrIsAppThemed pIsAppThemed; + static PtrIsThemeActive pIsThemeActive; + static PtrOpenThemeData pOpenThemeData; + static PtrCloseThemeData pCloseThemeData; + static PtrDrawThemeBackground pDrawThemeBackground; + static PtrDrawThemeBackgroundEx pDrawThemeBackgroundEx; + static PtrGetCurrentThemeName pGetCurrentThemeName; + static PtrGetThemeBool pGetThemeBool; + static PtrGetThemeColor pGetThemeColor; + static PtrGetThemeEnumValue pGetThemeEnumValue; + static PtrGetThemeFilename pGetThemeFilename; + static PtrGetThemeFont pGetThemeFont; + static PtrGetThemeInt pGetThemeInt; + static PtrGetThemeIntList pGetThemeIntList; + static PtrGetThemeMargins pGetThemeMargins; + static PtrGetThemeMetric pGetThemeMetric; + static PtrGetThemePartSize pGetThemePartSize; + static PtrGetThemePosition pGetThemePosition; + static PtrGetThemePropertyOrigin pGetThemePropertyOrigin; + static PtrGetThemeRect pGetThemeRect; + static PtrGetThemeString pGetThemeString; + static PtrGetThemeBackgroundRegion pGetThemeBackgroundRegion; + static PtrGetThemeDocumentationProperty pGetThemeDocumentationProperty; + static PtrIsThemeBackgroundPartiallyTransparent pIsThemeBackgroundPartiallyTransparent; + static PtrSetWindowTheme pSetWindowTheme; + static PtrGetThemeTransitionDuration pGetThemeTransitionDuration; // Windows Vista onwards. +}; + +class QWindowsXPStylePrivate : public QWindowsStylePrivate, public QWindowsUxThemeLib { Q_DECLARE_PUBLIC(QWindowsXPStyle) public: From fea21655a8b04553b438e866dfcccc5a3d6120a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 25 Jul 2014 16:03:28 +0200 Subject: [PATCH 16/89] iOS: Add support for QWindow::setOpacity() Change-Id: I027154aef35d219f08915e195f2baf8595ef7343 Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qioswindow.h | 1 + src/plugins/platforms/ios/qioswindow.mm | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h index bcff3e202c..e55def1992 100644 --- a/src/plugins/platforms/ios/qioswindow.h +++ b/src/plugins/platforms/ios/qioswindow.h @@ -73,6 +73,7 @@ public: void setParent(const QPlatformWindow *window); void handleContentOrientationChange(Qt::ScreenOrientation orientation); void setVisible(bool visible); + void setOpacity(qreal level) Q_DECL_OVERRIDE; bool isExposed() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index d8dd875d83..aa33a9b21d 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -74,6 +74,7 @@ QIOSWindow::QIOSWindow(QWindow *window) screen()->availableGeometry().width(), screen()->availableGeometry().height()); setWindowState(window->windowState()); + setOpacity(window->opacity()); } QIOSWindow::~QIOSWindow() @@ -135,6 +136,11 @@ void QIOSWindow::setVisible(bool visible) } } +void QIOSWindow::setOpacity(qreal level) +{ + m_view.alpha = qBound(0.0, level, 1.0); +} + void QIOSWindow::setGeometry(const QRect &rect) { m_normalGeometry = rect; From 942c6910d1bab87aebb258d4076386c00ce041ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 20 Aug 2014 17:19:26 +0200 Subject: [PATCH 17/89] iOS: Get rid of markedTextFormat global static variable in IME Preperation for IME refactor. Change-Id: I0832c174d05d019d69ef7c01c45aaedc6e4d9468 Reviewed-by: Richard Moe Gustavsen --- .../platforms/ios/quiview_textinput.mm | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/plugins/platforms/ios/quiview_textinput.mm b/src/plugins/platforms/ios/quiview_textinput.mm index 2280b8259a..6b2707e706 100644 --- a/src/plugins/platforms/ios/quiview_textinput.mm +++ b/src/plugins/platforms/ios/quiview_textinput.mm @@ -49,19 +49,11 @@ class StaticVariables public: QInputMethodQueryEvent inputMethodQueryEvent; bool inUpdateKeyboardLayout; - QTextCharFormat markedTextFormat; StaticVariables() : inputMethodQueryEvent(Qt::ImQueryInput) , inUpdateKeyboardLayout(false) { - // There seems to be no way to query how the preedit text - // should be drawn. So we need to hard-code the color. - QSysInfo::MacVersion iosVersion = QSysInfo::MacintoshVersion; - if (iosVersion < QSysInfo::MV_IOS_7_0) - markedTextFormat.setBackground(QColor(235, 239, 247)); - else - markedTextFormat.setBackground(QColor(206, 221, 238)); } }; @@ -301,8 +293,19 @@ Q_GLOBAL_STATIC(StaticVariables, staticVariables); m_markedText = markedText ? QString::fromNSString(markedText) : QString(); + static QTextCharFormat markedTextFormat; + if (markedTextFormat.isEmpty()) { + // There seems to be no way to query how the preedit text + // should be drawn. So we need to hard-code the color. + QSysInfo::MacVersion iosVersion = QSysInfo::MacintoshVersion; + if (iosVersion < QSysInfo::MV_IOS_7_0) + markedTextFormat.setBackground(QColor(235, 239, 247)); + else + markedTextFormat.setBackground(QColor(206, 221, 238)); + } + QList attrs; - attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, markedText.length, staticVariables()->markedTextFormat); + attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, markedText.length, markedTextFormat); QInputMethodEvent e(m_markedText, attrs); [self sendEventToFocusObject:e]; } From 8a7fcf0a7df833de56de4d7848c0f5f44ba1ee4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 29 Jul 2014 18:54:31 +0200 Subject: [PATCH 18/89] iOS: Don't store UIViewAnimationOptions value as UIViewAnimationCurve We pull out the magic UIViewAnimationCurve of the keyboard animation when the keyboard is about to show, but we need to defer the shifting of the value 16 bits, as that turns it into a UIViewAnimationOptions, which we can't store in a UIViewAnimationCurve member. Change-Id: Id35dae1ec487951df749dfffb6118b572c28b103 Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qiosinputcontext.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index d109d53168..064098157d 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -166,7 +166,7 @@ self.enabled = YES; if (!m_duration) { m_duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; - m_curve = UIViewAnimationCurve([[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue] << 16); + m_curve = UIViewAnimationCurve([[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue]); } m_context->scrollToCursor(); } @@ -389,7 +389,7 @@ void QIOSInputContext::scroll(int y) newBounds.origin.y = y; QPointer self = this; [UIView animateWithDuration:m_keyboardListener->m_duration delay:0 - options:m_keyboardListener->m_curve | UIViewAnimationOptionBeginFromCurrentState + options:(m_keyboardListener->m_curve << 16) | UIViewAnimationOptionBeginFromCurrentState animations:^{ view.bounds = newBounds; } completion:^(BOOL){ if (self) From 1a9992c1f2e44f5a2cb8daffa7bcf5b272d6bec4 Mon Sep 17 00:00:00 2001 From: Adam Strzelecki Date: Tue, 2 Sep 2014 20:31:22 +0200 Subject: [PATCH 19/89] Fix bash syntax error in configure Fixes missing space before `]` in test condition introduced in 8d5772533887266d. Change-Id: I741c291677f32056a0a0bec12cb4d9fd293a2021 Reviewed-by: Thiago Macieira --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 7cbd11d98d..0c65aac14a 100755 --- a/configure +++ b/configure @@ -6636,7 +6636,7 @@ if [ "$CFG_OPENSSL" = "linked" ] && [ "$OPENSSL_LIBS" = "" ]; then echo "For example:" echo " OPENSSL_LIBS='-L/opt/ssl/lib -lssl -lcrypto' ./configure -openssl-linked" fi -if [ "$CFG_JOURNALD" = "yes" ] || [ "$CFG_SLOG2" = "yes"]; then +if [ "$CFG_JOURNALD" = "yes" ] || [ "$CFG_SLOG2" = "yes" ]; then echo echo "NOTE: journald or slog2 integration is enabled." echo "If your users intend on developing applications against this build," From b04c14429734614fdb7c846a0c319512acee47cd Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 2 Sep 2014 10:16:16 +0200 Subject: [PATCH 20/89] QOpenGL2GradientCache::getBuffer: calculate hash value outside critical section The code doesn't touch any member variables, so it doesn't need mutex protection. Reducing the time spent under the mutex allows a higher speedup (Amdahl's Law), so do it. Also made the mutex locker const to indicate it is never unlock()ed again. Change-Id: Ic50b827c0e34d39cbddc7ec83675b568a9c33f6d Reviewed-by: Allan Sandfeld Jensen --- src/gui/opengl/qopenglgradientcache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/opengl/qopenglgradientcache.cpp b/src/gui/opengl/qopenglgradientcache.cpp index 91b4d08474..f8060fc6a0 100644 --- a/src/gui/opengl/qopenglgradientcache.cpp +++ b/src/gui/opengl/qopenglgradientcache.cpp @@ -102,13 +102,13 @@ void QOpenGL2GradientCache::cleanCache() GLuint QOpenGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity) { - QMutexLocker lock(&m_mutex); quint64 hash_val = 0; QGradientStops stops = gradient.stops(); for (int i = 0; i < stops.size() && i <= 2; i++) hash_val += stops[i].second.rgba(); + const QMutexLocker lock(&m_mutex); QOpenGLGradientColorTableHash::const_iterator it = cache.constFind(hash_val); if (it == cache.constEnd()) From 5b9e566b4d009ddb79f4c7d7e17ef0b8b4024859 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 2 Sep 2014 10:32:43 +0200 Subject: [PATCH 21/89] QImage: add a qMove() The color table is passed by value (good for C++11), so when the argument is assigned to the member variable, that's a good spot for a move assignment. However, the argument is also declared const. The standard says that top-level const is ignored, but some compilers (I know about SunCC) think differently, so we cannot remove it. Instead, we do a const_cast. It is well-defined: Even though apparently the argument was declared as const, the standard says the const is not there, and no sane compiler would put the argument copy into read-only memory. Add a reminder to remove the top-level const from the signature come Qt 6. Change-Id: Iac18846ba669de0a30da620685ad1438c267e193 Reviewed-by: Olivier Goffart --- src/gui/image/qimage.cpp | 2 +- src/gui/image/qimage.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index c3b4b1444a..5de686c1ea 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -1368,7 +1368,7 @@ void QImage::setColorTable(const QVector colors) if (!d) return; - d->colortable = colors; + d->colortable = qMove(const_cast&>(colors)); d->has_alpha_clut = false; for (int i = 0; i < d->colortable.size(); ++i) { if (qAlpha(d->colortable.at(i)) != 255) { diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 844bbb2eba..3e73462efc 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -232,7 +232,7 @@ public: void setPixel(const QPoint &pt, uint index_or_rgb); QVector colorTable() const; - void setColorTable(const QVector colors); + void setColorTable(const QVector colors); // ### Qt 6: remove const qreal devicePixelRatio() const; void setDevicePixelRatio(qreal scaleFactor); From efdabc4b0e2055b7600c97e49954e68dd0b09003 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Tue, 2 Sep 2014 11:57:02 +0300 Subject: [PATCH 22/89] Remove vestiges of d3dcompiler_qt Change-Id: I2a233cb0bfec27a7535a31818568955f8bf85c15 Reviewed-by: Friedemann Kleint --- src/src.pro | 1 - tests/auto/other/other.pro | 3 --- 2 files changed, 4 deletions(-) diff --git a/src/src.pro b/src/src.pro index 13f62137ec..ab93641131 100644 --- a/src/src.pro +++ b/src/src.pro @@ -85,7 +85,6 @@ src_3rdparty_harfbuzzng.target = sub-3rdparty-harfbuzzng src_angle.subdir = $$PWD/angle src_angle.target = sub-angle -angle_d3d11: src_angle.depends = src_corelib src_gui.subdir = $$PWD/gui src_gui.target = sub-gui diff --git a/tests/auto/other/other.pro b/tests/auto/other/other.pro index 745c8f2499..bd3997f8c9 100644 --- a/tests/auto/other/other.pro +++ b/tests/auto/other/other.pro @@ -3,7 +3,6 @@ SUBDIRS=\ # atwrapper \ # QTBUG-19452 baselineexample \ compiler \ - d3dcompiler \ gestures \ headersclean \ lancelot \ @@ -58,8 +57,6 @@ cross_compile: SUBDIRS -= \ wince*|!contains(QT_CONFIG, accessibility): SUBDIRS -= qaccessibility -!angle_d3d11: SUBDIRS -= d3dcompiler - !contains(QT_CONFIG, accessibility-atspi-bridge): SUBDIRS -= qaccessibilitylinux !mac: SUBDIRS -= \ From a8b243b42e95094b4b464eed884b641cc1cbdbf4 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 1 Sep 2014 14:39:17 +0300 Subject: [PATCH 23/89] windows: Allow selection of ANGLE's renderer The default behavior of ANGLE is to use D3D11 before falling back to D3D9. This change improves flexibility the platform plugin to explicitly create a D3D11, D3D9, or D3D11 software (WARP) context by setting the QT_ANGLE_PLATFORM to "d3d11", "d3d9", or "warp", respectively. Task-number: QTBUG-41031 Change-Id: Ie1d399c1cb0e360e5b3a6d9f2a4b28745d86cc71 Reviewed-by: Friedemann Kleint Reviewed-by: Laszlo Agocs --- .../platforms/windows/qwindowseglcontext.cpp | 31 ++++++++++++++++++- .../platforms/windows/qwindowseglcontext.h | 1 + 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 2d2d409a0f..698a153533 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -46,6 +46,10 @@ #include #include +#if defined(QT_OPENGL_ES_2_ANGLE) +# include +#endif + QT_BEGIN_NAMESPACE /*! @@ -140,6 +144,7 @@ bool QWindowsLibEGL::init() eglGetError = RESOLVE((EGLint (EGLAPIENTRY *)(void)), eglGetError); eglGetDisplay = RESOLVE((EGLDisplay (EGLAPIENTRY *)(EGLNativeDisplayType)), eglGetDisplay); + eglGetPlatformDisplayEXT = RESOLVE((EGLDisplay (EGLAPIENTRY *)(EGLenum platform, void *native_display, const EGLint *attrib_list)), eglGetPlatformDisplayEXT); eglInitialize = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLint *, EGLint *)), eglInitialize); eglTerminate = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay)), eglTerminate); eglChooseConfig = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, const EGLint *, EGLConfig *, EGLint, EGLint *)), eglChooseConfig); @@ -359,7 +364,31 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create() return 0; } - EGLDisplay display = libEGL.eglGetDisplay((EGLNativeDisplayType)dc); + EGLDisplay display = EGL_NO_DISPLAY; +#ifdef EGL_ANGLE_platform_angle_opengl + if (libEGL.eglGetPlatformDisplayEXT && qEnvironmentVariableIsSet("QT_ANGLE_PLATFORM")) { + const EGLint anglePlatformAttributes[][3] = { + { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_NONE }, + { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, EGL_NONE }, + { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE, EGL_NONE } + }; + const EGLint *attributes = 0; + const QByteArray anglePlatform = qgetenv("QT_ANGLE_PLATFORM"); + if (anglePlatform == "d3d11") + attributes = anglePlatformAttributes[0]; + else if (anglePlatform == "d3d9") + attributes = anglePlatformAttributes[1]; + else if (anglePlatform == "warp") + attributes = anglePlatformAttributes[2]; + else + qCWarning(lcQpaGl) << "Invalid value set for QT_ANGLE_PLATFORM:" << anglePlatform; + + if (attributes) + display = libEGL.eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, dc, attributes); + } +#endif // EGL_ANGLE_platform_angle_opengl + if (display == EGL_NO_DISPLAY) + display = libEGL.eglGetDisplay((EGLNativeDisplayType)dc); if (!display) { qWarning("%s: Could not obtain EGL display", Q_FUNC_INFO); return 0; diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h index 6c4ac08da1..a7866516f0 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.h +++ b/src/plugins/platforms/windows/qwindowseglcontext.h @@ -53,6 +53,7 @@ struct QWindowsLibEGL EGLint (EGLAPIENTRY * eglGetError)(void); EGLDisplay (EGLAPIENTRY * eglGetDisplay)(EGLNativeDisplayType display_id); + EGLDisplay (EGLAPIENTRY * eglGetPlatformDisplayEXT)(EGLenum platform, void *native_display, const EGLint *attrib_list); EGLBoolean (EGLAPIENTRY * eglInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor); EGLBoolean (EGLAPIENTRY * eglTerminate)(EGLDisplay dpy); EGLBoolean (EGLAPIENTRY * eglChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list, From d450eb5e6da5a7f2a14bbf02b3c167962e0618fd Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Tue, 2 Sep 2014 12:58:53 +0200 Subject: [PATCH 24/89] Android: Guard against invalid surfaceID Do not try to resize or destroy invalid surfaces. This caused update problems with all GL apps after suspend, since we would forget the dummy view that we always keep around so we get proper transitions on shutdown. Also make sure that we don't mess this up even if we try to destroy a non-existing surface. This would have fixed the bug by itself, but then we would still be stuck with the annoying warning message. Task-number: QTBUG-41093 Change-Id: I83299e93eb9ac5357b98ca47014789b56c91b35a Reviewed-by: Christian Stromme --- .../src/org/qtproject/qt5/android/QtActivityDelegate.java | 5 ++++- src/plugins/platforms/android/androidjnimain.cpp | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) 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 b4b483b416..01aa55c19e 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -1085,11 +1085,14 @@ public class QtActivityDelegate Log.e(QtNative.QtTAG, "Surface " + id +" not found!"); } + if (view == null) + return; + // Keep last frame in stack until it is replaced to get correct // shutdown transition if (m_surfaces.size() == 0 && m_nativeViews.size() == 0) { m_dummyView = view; - } else if (view != null) { + } else { m_layout.removeView(view); } } diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index de30fa825a..7b76177141 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -380,6 +380,9 @@ namespace QtAndroid void setSurfaceGeometry(int surfaceId, const QRect &geometry) { + if (surfaceId == -1) + return; + QJNIEnvironmentPrivate env; if (!env) return; @@ -399,6 +402,9 @@ namespace QtAndroid void destroySurface(int surfaceId) { + if (surfaceId == -1) + return; + QMutexLocker lock(&m_surfacesMutex); const auto &it = m_surfaces.find(surfaceId); if (it != m_surfaces.end()) From b17365cda91a6ecc8d12e995d83f4ff479c59b5f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 5 Aug 2014 15:05:49 +0200 Subject: [PATCH 25/89] Fix drawing of QLineEdit's actions when Qt::AA_UseHighDpiPixmaps is set. Task-number: QTBUG-40525 Change-Id: Iff3c1e16d9c44e1d36b8f83ca96b48bff05ab1f0 Reviewed-by: Marc Mutz Reviewed-by: Giuseppe D'Angelo --- src/widgets/widgets/qlineedit_p.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index 7ad893a54e..58ec068bb2 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -324,7 +324,7 @@ void QLineEditIconButton::paintEvent(QPaintEvent *) state = isDown() ? QIcon::Selected : QIcon::Normal; const QPixmap iconPixmap = icon().pixmap(QSize(IconButtonSize, IconButtonSize), state, QIcon::Off); - QRect pixmapRect = QRect(0, 0, iconPixmap.width(), iconPixmap.height()); + QRect pixmapRect = QRect(QPoint(0, 0), iconPixmap.size() / iconPixmap.devicePixelRatio()); pixmapRect.moveCenter(rect().center()); painter.setOpacity(m_opacity); painter.drawPixmap(pixmapRect, iconPixmap); From cd3dece750aa30b15091f211a72b6fcf67d49853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeremy=20Lain=C3=A9?= Date: Sun, 31 Aug 2014 14:55:06 +0300 Subject: [PATCH 26/89] ssl: common key parser support for encrypted keys This adds the infrastructure for reading and writing encrypted private keys when using non-OpenSSL backends. Each platform must provide its cryptographic encrypt / decrypt functions. As WinRT already uses the common parser, this commit includes an implementation for that platform. Done-with: Andrew Knight Task-number: QTBUG-40688 Change-Id: I0d153425ce63601ff03b784a111e13962061025f Reviewed-by: Richard J. Moore --- src/network/ssl/qsslkey_openssl.cpp | 3 +- src/network/ssl/qsslkey_p.cpp | 52 +++++++- src/network/ssl/qsslkey_p.h | 13 +- src/network/ssl/qsslkey_qt.cpp | 78 +++++++++-- src/network/ssl/qsslkey_winrt.cpp | 98 ++++++++++++++ tests/auto/network/ssl/qsslkey/qsslkey.pro | 3 + .../ssl/qsslkey/rsa-with-passphrase-rc2.pem | 18 +++ .../auto/network/ssl/qsslkey/tst_qsslkey.cpp | 126 ++++++++++++++++-- 8 files changed, 367 insertions(+), 24 deletions(-) create mode 100644 tests/auto/network/ssl/qsslkey/rsa-with-passphrase-rc2.pem diff --git a/src/network/ssl/qsslkey_openssl.cpp b/src/network/ssl/qsslkey_openssl.cpp index 7e78ac0fee..6b0fa954eb 100644 --- a/src/network/ssl/qsslkey_openssl.cpp +++ b/src/network/ssl/qsslkey_openssl.cpp @@ -111,7 +111,8 @@ bool QSslKeyPrivate::fromEVP_PKEY(EVP_PKEY *pkey) void QSslKeyPrivate::decodeDer(const QByteArray &der, bool deepClear) { - decodePem(pemFromDer(der), QByteArray(), deepClear); + QMap headers; + decodePem(pemFromDer(der, headers), QByteArray(), deepClear); } void QSslKeyPrivate::decodePem(const QByteArray &pem, const QByteArray &passPhrase, diff --git a/src/network/ssl/qsslkey_p.cpp b/src/network/ssl/qsslkey_p.cpp index 2b0dab9933..b051ec6874 100644 --- a/src/network/ssl/qsslkey_p.cpp +++ b/src/network/ssl/qsslkey_p.cpp @@ -63,6 +63,7 @@ #include #include +#include #include #ifndef QT_NO_DEBUG_STREAM #include @@ -130,7 +131,7 @@ QByteArray QSslKeyPrivate::pemFooter() const Returns a DER key formatted as PEM. */ -QByteArray QSslKeyPrivate::pemFromDer(const QByteArray &der) const +QByteArray QSslKeyPrivate::pemFromDer(const QByteArray &der, const QMap &headers) const { QByteArray pem(der.toBase64()); @@ -144,7 +145,16 @@ QByteArray QSslKeyPrivate::pemFromDer(const QByteArray &der) const if (rem) pem.append('\n'); // ### - pem.prepend(pemHeader() + '\n'); + QByteArray extra; + if (!headers.isEmpty()) { + QMap::const_iterator it = headers.constEnd(); + do { + it--; + extra += it.key() + ": " + it.value() + '\n'; + } while (it != headers.constBegin()); + extra += '\n'; + } + pem.prepend(pemHeader() + '\n' + extra); pem.append(pemFooter() + '\n'); return pem; @@ -155,7 +165,7 @@ QByteArray QSslKeyPrivate::pemFromDer(const QByteArray &der) const Returns a PEM key formatted as DER. */ -QByteArray QSslKeyPrivate::derFromPem(const QByteArray &pem) const +QByteArray QSslKeyPrivate::derFromPem(const QByteArray &pem, QMap *headers) const { const QByteArray header = pemHeader(); const QByteArray footer = pemFooter(); @@ -169,6 +179,39 @@ QByteArray QSslKeyPrivate::derFromPem(const QByteArray &pem) const der = der.mid(headerIndex + header.size(), footerIndex - (headerIndex + header.size())); + if (der.contains("Proc-Type:")) { + // taken from QHttpNetworkReplyPrivate::parseHeader + const QByteArrayMatcher lf("\n"); + const QByteArrayMatcher colon(":"); + int i = 0; + while (i < der.count()) { + int j = colon.indexIn(der, i); // field-name + if (j == -1) + break; + const QByteArray field = der.mid(i, j - i).trimmed(); + j++; + // any number of LWS is allowed before and after the value + QByteArray value; + do { + i = lf.indexIn(der, j); + if (i == -1) + break; + if (!value.isEmpty()) + value += ' '; + // check if we have CRLF or only LF + bool hasCR = (i && der[i-1] == '\r'); + int length = i -(hasCR ? 1: 0) - j; + value += der.mid(j, length).trimmed(); + j = ++i; + } while (i < der.count() && (der.at(i) == ' ' || der.at(i) == '\t')); + if (i == -1) + break; // something is wrong + + headers->insert(field, value); + } + der = der.mid(i); + } + return QByteArray::fromBase64(der); // ignores newlines } @@ -337,7 +380,8 @@ QByteArray QSslKey::toDer(const QByteArray &passPhrase) const return QByteArray(); #ifndef QT_NO_OPENSSL - return d->derFromPem(toPem(passPhrase)); + QMap headers; + return d->derFromPem(toPem(passPhrase), &headers); #else return d->derData; #endif diff --git a/src/network/ssl/qsslkey_p.h b/src/network/ssl/qsslkey_p.h index 9c1476038a..d24606e6a6 100644 --- a/src/network/ssl/qsslkey_p.h +++ b/src/network/ssl/qsslkey_p.h @@ -91,8 +91,8 @@ public: bool deepClear = true); QByteArray pemHeader() const; QByteArray pemFooter() const; - QByteArray pemFromDer(const QByteArray &der) const; - QByteArray derFromPem(const QByteArray &pem) const; + QByteArray pemFromDer(const QByteArray &der, const QMap &headers) const; + QByteArray derFromPem(const QByteArray &pem, QMap *headers) const; int length() const; QByteArray toPem(const QByteArray &passPhrase) const; @@ -106,6 +106,15 @@ public: RSA *rsa; DSA *dsa; #else + enum Cipher { + DesCbc, + DesEde3Cbc, + Rc2Cbc + }; + + Q_AUTOTEST_EXPORT static QByteArray decrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv); + Q_AUTOTEST_EXPORT static QByteArray encrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv); + Qt::HANDLE opaque; QByteArray derData; int keyLength; diff --git a/src/network/ssl/qsslkey_qt.cpp b/src/network/ssl/qsslkey_qt.cpp index feeb7d6f87..c14cf0250c 100644 --- a/src/network/ssl/qsslkey_qt.cpp +++ b/src/network/ssl/qsslkey_qt.cpp @@ -43,6 +43,8 @@ #include "qsslkey_p.h" #include "qasn1element_p.h" +#include + QT_USE_NAMESPACE static const quint8 bits_table[256] = { @@ -78,6 +80,31 @@ static int numberOfBits(const QByteArray &modulus) return bits; } +static QByteArray deriveKey(QSslKeyPrivate::Cipher cipher, const QByteArray &passPhrase, const QByteArray &iv) +{ + QByteArray key; + QCryptographicHash hash(QCryptographicHash::Md5); + hash.addData(passPhrase); + hash.addData(iv); + switch (cipher) { + case QSslKeyPrivate::DesCbc: + key = hash.result().left(8); + break; + case QSslKeyPrivate::DesEde3Cbc: + key = hash.result(); + hash.reset(); + hash.addData(key); + hash.addData(passPhrase); + hash.addData(iv); + key += hash.result().left(8); + break; + case QSslKeyPrivate::Rc2Cbc: + key = hash.result(); + break; + } + return key; +} + void QSslKeyPrivate::clear(bool deep) { Q_UNUSED(deep); @@ -155,12 +182,32 @@ void QSslKeyPrivate::decodeDer(const QByteArray &der, bool deepClear) void QSslKeyPrivate::decodePem(const QByteArray &pem, const QByteArray &passPhrase, bool deepClear) { - if (type == QSsl::PrivateKey && !passPhrase.isEmpty()) { - Q_UNIMPLEMENTED(); - return; - } + QMap headers; + QByteArray data = derFromPem(pem, &headers); + if (headers.value("Proc-Type") == "4,ENCRYPTED") { + QList dekInfo = headers.value("DEK-Info").split(','); + if (dekInfo.size() != 2) { + clear(deepClear); + return; + } - decodeDer(derFromPem(pem), deepClear); + Cipher cipher; + if (dekInfo.first() == "DES-CBC") { + cipher = DesCbc; + } else if (dekInfo.first() == "DES-EDE3-CBC") { + cipher = DesEde3Cbc; + } else if (dekInfo.first() == "RC2-CBC") { + cipher = Rc2Cbc; + } else { + clear(deepClear); + return; + } + + const QByteArray iv = QByteArray::fromHex(dekInfo.last()); + const QByteArray key = deriveKey(cipher, passPhrase, iv); + data = decrypt(cipher, data, key, iv); + } + decodeDer(data, deepClear); } int QSslKeyPrivate::length() const @@ -170,12 +217,27 @@ int QSslKeyPrivate::length() const QByteArray QSslKeyPrivate::toPem(const QByteArray &passPhrase) const { + QByteArray data; + QMap headers; + if (type == QSsl::PrivateKey && !passPhrase.isEmpty()) { - Q_UNIMPLEMENTED(); - return QByteArray(); + // ### use a cryptographically secure random number generator + QByteArray iv; + iv.resize(8); + for (int i = 0; i < iv.size(); ++i) + iv[i] = (qrand() & 0xff); + + Cipher cipher = DesEde3Cbc; + const QByteArray key = deriveKey(cipher, passPhrase, iv); + data = encrypt(cipher, derData, key, iv); + + headers.insert("Proc-Type", "4,ENCRYPTED"); + headers.insert("DEK-Info", "DES-EDE3-CBC," + iv.toHex()); + } else { + data = derData; } - return pemFromDer(derData); + return pemFromDer(data, headers); } Qt::HANDLE QSslKeyPrivate::handle() const diff --git a/src/network/ssl/qsslkey_winrt.cpp b/src/network/ssl/qsslkey_winrt.cpp index 2c83069694..c5b4146ee9 100644 --- a/src/network/ssl/qsslkey_winrt.cpp +++ b/src/network/ssl/qsslkey_winrt.cpp @@ -61,3 +61,101 @@ using namespace ABI::Windows::Security::Cryptography::Core; using namespace ABI::Windows::Storage::Streams; QT_USE_NAMESPACE + +struct SslKeyGlobal +{ + SslKeyGlobal() + { + HRESULT hr; + hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Security_Cryptography_Core_CryptographicEngine).Get(), + &engine); + Q_ASSERT_SUCCEEDED(hr); + + ComPtr keyProviderFactory; + hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Security_Cryptography_Core_SymmetricKeyAlgorithmProvider).Get(), + &keyProviderFactory); + Q_ASSERT_SUCCEEDED(hr); + hr = keyProviderFactory->OpenAlgorithm(HString::MakeReference(L"DES_CBC").Get(), + &keyProviders[QSslKeyPrivate::DesCbc]); + Q_ASSERT_SUCCEEDED(hr); + hr = keyProviderFactory->OpenAlgorithm(HString::MakeReference(L"3DES_CBC").Get(), + &keyProviders[QSslKeyPrivate::DesEde3Cbc]); + Q_ASSERT_SUCCEEDED(hr); + hr = keyProviderFactory->OpenAlgorithm(HString::MakeReference(L"RC2_CBC").Get(), + &keyProviders[QSslKeyPrivate::Rc2Cbc]); + Q_ASSERT_SUCCEEDED(hr); + + hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Security_Cryptography_CryptographicBuffer).Get(), + &bufferFactory); + Q_ASSERT_SUCCEEDED(hr); + } + + ComPtr engine; + QHash> keyProviders; + ComPtr bufferFactory; +}; +Q_GLOBAL_STATIC(SslKeyGlobal, g) + +static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, QByteArray data, const QByteArray &key, const QByteArray &iv, bool encrypt) +{ + HRESULT hr; + + ISymmetricKeyAlgorithmProvider *keyProvider = g->keyProviders[cipher].Get(); + Q_ASSERT(keyProvider); + + ComPtr keyBuffer; + hr = g->bufferFactory->CreateFromByteArray(key.length(), (BYTE *)key.data(), &keyBuffer); + Q_ASSERT_SUCCEEDED(hr); + ComPtr cryptographicKey; + hr = keyProvider->CreateSymmetricKey(keyBuffer.Get(), &cryptographicKey); + Q_ASSERT_SUCCEEDED(hr); + + UINT32 blockLength; + hr = keyProvider->get_BlockLength(&blockLength); + Q_ASSERT_SUCCEEDED(hr); + if (encrypt) { // Add padding + const char padding = blockLength - data.length() % blockLength; + data += QByteArray(padding, padding); + } + + ComPtr dataBuffer; + hr = g->bufferFactory->CreateFromByteArray(data.length(), (BYTE *)data.data(), &dataBuffer); + Q_ASSERT_SUCCEEDED(hr); + ComPtr ivBuffer; + hr = g->bufferFactory->CreateFromByteArray(iv.length(), (BYTE *)iv.data(), &ivBuffer); + Q_ASSERT_SUCCEEDED(hr); + ComPtr resultBuffer; + hr = encrypt ? g->engine->Encrypt(cryptographicKey.Get(), dataBuffer.Get(), ivBuffer.Get(), &resultBuffer) + : g->engine->Decrypt(cryptographicKey.Get(), dataBuffer.Get(), ivBuffer.Get(), &resultBuffer); + Q_ASSERT_SUCCEEDED(hr); + + UINT32 resultLength; + hr = resultBuffer->get_Length(&resultLength); + Q_ASSERT_SUCCEEDED(hr); + ComPtr bufferAccess; + hr = resultBuffer.As(&bufferAccess); + Q_ASSERT_SUCCEEDED(hr); + byte *resultData; + hr = bufferAccess->Buffer(&resultData); + Q_ASSERT_SUCCEEDED(hr); + + if (!encrypt) { // Remove padding + const uchar padding = resultData[resultLength - 1]; + if (padding > 0 && padding <= blockLength) + resultLength -= padding; + else + qWarning("Invalid padding length of %u; decryption likely failed.", padding); + } + + return QByteArray(reinterpret_cast(resultData), resultLength); +} + +QByteArray QSslKeyPrivate::decrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv) +{ + return doCrypt(cipher, data, key, iv, false); +} + +QByteArray QSslKeyPrivate::encrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv) +{ + return doCrypt(cipher, data, key, iv, true); +} diff --git a/tests/auto/network/ssl/qsslkey/qsslkey.pro b/tests/auto/network/ssl/qsslkey/qsslkey.pro index 78cfb9ce92..4ec4f27e6f 100644 --- a/tests/auto/network/ssl/qsslkey/qsslkey.pro +++ b/tests/auto/network/ssl/qsslkey/qsslkey.pro @@ -4,6 +4,9 @@ CONFIG += parallel_test SOURCES += tst_qsslkey.cpp !wince*:win32:LIBS += -lws2_32 QT = core network testlib +contains(QT_CONFIG, private_tests) { + QT += core-private network-private +} TARGET = tst_qsslkey diff --git a/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-rc2.pem b/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-rc2.pem new file mode 100644 index 0000000000..7a0722fb8d --- /dev/null +++ b/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-rc2.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: RC2-CBC,EAAF396E2CDD3680 + +G+kY27Vq0Bkw6dEGlpe4oyyXlilyKJgkX53NQHv0WtLsu+cfamGst9viSQbAluP0 +Pk2m78Z05IZHBkxcl20tZZR3G3hFTVqf7OemEucT5Kb/Vx6V++ZXY5eI54bh1oEJ +f8klr2DnscyTYdT33cmMuaxUm1sWjHeBBdQuQlMnW11XoCiGQMgMyf2fwbzd/og+ +vDPtORIMw+zedxaTsiOyNASLWB5ILDpUR9PTzz1tRIIOF5DnKttEe3SYPIqkLhxu +N7OtpVhor0QUulph8sS2uiilTVyaYVciOJK7Cqq2K015l9nlqGg/KI0GRIC9ty+k +wd+/Hdazp+YcLn3tL8jhekST/DAxK9VIb0DBvaboKr8UJw35nLOwA7smsij50l2S +kfpu9z/80gFbnSSQo7L8zD/kBzaPlup0H+h96rF3IjdCrnbveHlvJDo3GcPNxauw +rGUQXnnMzDVSTY179HfcgLZdsm3uOIBicEFaxXu2/L4Eof9yp8D/b6SeZeS41O7a +ICvLXxkiIfQHukHvqMLJ2SqKQ0J8zEXN0OBSLjaHUkBIOs3L4IFe2v8DMN798GrG +QzcxC0bmr9s6TvihlYFBbYkMZ3IYPT4SFZg92/pKTPlyD/Blc9oZm8QpQMGIMDKc +nWDLeqeCTXV6TL1mymqzwyzs9+4cXvEiM167FsLqk5tGRIyl4AR/dItELEtCWl3I +koIOUEk5rbJekOhTc85SFSQmCV0IebsUv0CpdWlmNeexNryLZu0r6kTUFWzpHcv/ +0yEaBQFLVx9QAfRSIiNt+yAgGnpMxxMxeHs6shVmuscZ0fV50GpOpA== +-----END RSA PRIVATE KEY----- diff --git a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp index 642b115bee..1c16f47ad6 100644 --- a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp +++ b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp @@ -47,6 +47,11 @@ #include #include +#if !defined(QT_NO_SSL) && defined(QT_NO_OPENSSL) && defined(QT_BUILD_INTERNAL) +#include "private/qsslkey_p.h" +#define TEST_CRYPTO +#endif + class tst_QSslKey : public QObject { Q_OBJECT @@ -90,6 +95,11 @@ private slots: void passphraseChecks_data(); void passphraseChecks(); void noPassphraseChecks(); +#ifdef TEST_CRYPTO + void encrypt_data(); + void encrypt(); +#endif + #endif private: QString testDataDir; @@ -306,9 +316,6 @@ void tst_QSslKey::toEncryptedPemOrDer() QByteArray pwBytes(password.toLatin1()); if (type == QSsl::PrivateKey) { -#ifdef QT_NO_OPENSSL - QSKIP("Encrypted keys require support from the SSL backend"); -#endif QByteArray encryptedPem = key.toPem(pwBytes); QVERIFY(!encryptedPem.isEmpty()); QSslKey keyPem(encryptedPem, algorithm, QSsl::Pem, type, pwBytes); @@ -347,6 +354,7 @@ void tst_QSslKey::passphraseChecks_data() QTest::newRow("DES") << QString(testDataDir + "/rsa-with-passphrase-des.pem"); QTest::newRow("3DES") << QString(testDataDir + "/rsa-with-passphrase-3des.pem"); + QTest::newRow("RC2") << QString(testDataDir + "/rsa-with-passphrase-rc2.pem"); } void tst_QSslKey::passphraseChecks() @@ -379,9 +387,6 @@ void tst_QSslKey::passphraseChecks() QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey, "WRONG!"); QVERIFY(key.isNull()); // wrong passphrase => should not be able to decode key } -#ifdef QT_NO_OPENSSL - QEXPECT_FAIL("", "Encrypted keys require support from the SSL backend", Abort); -#endif { if (!keyFile.isOpen()) keyFile.open(QIODevice::ReadOnly); @@ -413,9 +418,6 @@ void tst_QSslKey::noPassphraseChecks() QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey, ""); QVERIFY(!key.isNull()); // empty passphrase => should be able to decode key } -#ifdef QT_NO_OPENSSL - QEXPECT_FAIL("", "Encrypted keys require support from the SSL backend", Abort); -#endif { if (!keyFile.isOpen()) keyFile.open(QIODevice::ReadOnly); @@ -426,6 +428,112 @@ void tst_QSslKey::noPassphraseChecks() } } +#ifdef TEST_CRYPTO +Q_DECLARE_METATYPE(QSslKeyPrivate::Cipher) + +void tst_QSslKey::encrypt_data() +{ + QTest::addColumn("cipher"); + QTest::addColumn("key"); + QTest::addColumn("plainText"); + QTest::addColumn("cipherText"); + + QTest::newRow("DES-CBC, length 0") + << QSslKeyPrivate::DesCbc << QByteArray("01234567") + << QByteArray() + << QByteArray::fromHex("956585228BAF9B1F"); + QTest::newRow("DES-CBC, length 1") + << QSslKeyPrivate::DesCbc << QByteArray("01234567") + << QByteArray(1, 'a') + << QByteArray::fromHex("E6880AF202BA3C12"); + QTest::newRow("DES-CBC, length 2") + << QSslKeyPrivate::DesCbc << QByteArray("01234567") + << QByteArray(2, 'a') + << QByteArray::fromHex("A82492386EED6026"); + QTest::newRow("DES-CBC, length 3") + << QSslKeyPrivate::DesCbc << QByteArray("01234567") + << QByteArray(3, 'a') + << QByteArray::fromHex("90B76D5B79519CBA"); + QTest::newRow("DES-CBC, length 4") + << QSslKeyPrivate::DesCbc << QByteArray("01234567") + << QByteArray(4, 'a') + << QByteArray::fromHex("63E3DD6FED87052A"); + QTest::newRow("DES-CBC, length 5") + << QSslKeyPrivate::DesCbc << QByteArray("01234567") + << QByteArray(5, 'a') + << QByteArray::fromHex("03ACDB0EACBDFA94"); + QTest::newRow("DES-CBC, length 6") + << QSslKeyPrivate::DesCbc << QByteArray("01234567") + << QByteArray(6, 'a') + << QByteArray::fromHex("7D95024E42A3A88A"); + QTest::newRow("DES-CBC, length 7") + << QSslKeyPrivate::DesCbc << QByteArray("01234567") + << QByteArray(7, 'a') + << QByteArray::fromHex("5003436B8A8E42E9"); + QTest::newRow("DES-CBC, length 8") + << QSslKeyPrivate::DesCbc << QByteArray("01234567") + << QByteArray(8, 'a') + << QByteArray::fromHex("E4C1F054BF5521C0A4A0FD4A2BC6C1B1"); + + QTest::newRow("DES-EDE3-CBC, length 0") + << QSslKeyPrivate::DesEde3Cbc << QByteArray("0123456789abcdefghijklmn") + << QByteArray() + << QByteArray::fromHex("3B2B4CD0B0FD495F"); + QTest::newRow("DES-EDE3-CBC, length 8") + << QSslKeyPrivate::DesEde3Cbc << QByteArray("0123456789abcdefghijklmn") + << QByteArray(8, 'a') + << QByteArray::fromHex("F2A5A87763C54A72A3224103D90CDB03"); + + QTest::newRow("RC2-40-CBC, length 0") + << QSslKeyPrivate::Rc2Cbc << QByteArray("01234") + << QByteArray() + << QByteArray::fromHex("6D05D52392FF6E7A"); + QTest::newRow("RC2-40-CBC, length 8") + << QSslKeyPrivate::Rc2Cbc << QByteArray("01234") + << QByteArray(8, 'a') + << QByteArray::fromHex("75768E64C5749072A5D168F3AFEB0005"); + + QTest::newRow("RC2-64-CBC, length 0") + << QSslKeyPrivate::Rc2Cbc << QByteArray("01234567") + << QByteArray() + << QByteArray::fromHex("ADAE6BF70F420130"); + QTest::newRow("RC2-64-CBC, length 8") + << QSslKeyPrivate::Rc2Cbc << QByteArray("01234567") + << QByteArray(8, 'a') + << QByteArray::fromHex("C7BF5C80AFBE9FBEFBBB9FD935F6D0DF"); + + QTest::newRow("RC2-128-CBC, length 0") + << QSslKeyPrivate::Rc2Cbc << QByteArray("012345679abcdefg") + << QByteArray() + << QByteArray::fromHex("1E965D483A13C8FB"); + QTest::newRow("RC2-128-CBC, length 8") + << QSslKeyPrivate::Rc2Cbc << QByteArray("012345679abcdefg") + << QByteArray(8, 'a') + << QByteArray::fromHex("5AEC1A5B295660B02613454232F7DECE"); +} + +void tst_QSslKey::encrypt() +{ + QFETCH(QSslKeyPrivate::Cipher, cipher); + QFETCH(QByteArray, key); + QFETCH(QByteArray, plainText); + QFETCH(QByteArray, cipherText); + QByteArray iv("abcdefgh"); + +#ifdef Q_OS_WINRT + QEXPECT_FAIL("RC2-40-CBC, length 0", "WinRT treats RC2 as 128-bit", Abort); + QEXPECT_FAIL("RC2-40-CBC, length 8", "WinRT treats RC2 as 128-bit", Abort); + QEXPECT_FAIL("RC2-64-CBC, length 0", "WinRT treats RC2 as 128-bit", Abort); + QEXPECT_FAIL("RC2-64-CBC, length 8", "WinRT treats RC2 as 128-bit", Abort); +#endif + QByteArray encrypted = QSslKeyPrivate::encrypt(cipher, plainText, key, iv); + QCOMPARE(encrypted, cipherText); + + QByteArray decrypted = QSslKeyPrivate::decrypt(cipher, cipherText, key, iv); + QCOMPARE(decrypted, plainText); +} +#endif + #endif QTEST_MAIN(tst_QSslKey) From 365c6e81be0f09cf92ec4ed5a62f9951517859e7 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Wed, 3 Sep 2014 09:20:16 +0200 Subject: [PATCH 27/89] WinRT: Fixed construction of QNativeSocketEngine without parent Change-Id: If55a8049224a7dceca33a3cf3089d541a3a97b8e Reviewed-by: Andrew Knight --- src/network/socket/qnativesocketengine_winrt.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 2ea6d6e015..62b067750c 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -176,10 +176,8 @@ QNativeSocketEngine::QNativeSocketEngine(QObject *parent) { #ifndef QT_NO_SSL Q_D(QNativeSocketEngine); - Q_ASSERT(parent); - d->sslSocket = qobject_cast(parent->parent()); -#else - d->sslSocket = Q_NULLPTR; + if (parent) + d->sslSocket = qobject_cast(parent->parent()); #endif connect(this, SIGNAL(connectionReady()), SLOT(connectionNotification()), Qt::QueuedConnection); @@ -827,6 +825,7 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() , notifyOnException(false) , closingDown(false) , socketDescriptor(-1) + , sslSocket(Q_NULLPTR) { } From 1ce0acfb141a899ec91f7586015c13c5aa3f0137 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Mon, 1 Sep 2014 10:31:46 +0200 Subject: [PATCH 28/89] Doc: Do not include the external sites by default Move the line that adds the external page definions into its own separate include file. This prevents the files from being included in every Qt documentation module by default, needlessly duplicating the information. Currently only the QtDoc module (and modules that depend on QtDoc) need it. Task-number: QTBUG-41003 Change-Id: Ie2ddd3a645ea731787daacfffb3068cb36c79c9a Reviewed-by: Martin Smith Reviewed-by: Venugopal Shivashankar --- doc/global/externalsites.qdocconf | 3 +++ doc/global/fileextensions.qdocconf | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 doc/global/externalsites.qdocconf diff --git a/doc/global/externalsites.qdocconf b/doc/global/externalsites.qdocconf new file mode 100644 index 0000000000..46ce8401c0 --- /dev/null +++ b/doc/global/externalsites.qdocconf @@ -0,0 +1,3 @@ +# Include the external websites +sourcedirs += externalsites + diff --git a/doc/global/fileextensions.qdocconf b/doc/global/fileextensions.qdocconf index ec47dc9c7f..0a106d5bef 100644 --- a/doc/global/fileextensions.qdocconf +++ b/doc/global/fileextensions.qdocconf @@ -8,5 +8,3 @@ examples.imageextensions = "*.png *.jpg *.gif" headers.fileextensions = "*.ch *.h *.h++ *.hh *.hpp *.hxx" sources.fileextensions = "*.c++ *.cc *.cpp *.cxx *.mm *.qml *.qdoc" -#include the external websites -sourcedirs += externalsites From 8d0e6000cb326130605b2b5e688e9cdc65950794 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Wed, 3 Sep 2014 09:58:19 +0200 Subject: [PATCH 29/89] WinRT: Fixed initialization of udp socket udpSocket() can only be called after the socket descriptor is set. Change-Id: If651ff58507cd66c98de4b699a80149913d9ffcf Reviewed-by: Andrew Knight --- src/network/socket/qnativesocketengine_winrt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 62b067750c..4825d223ee 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -807,8 +807,8 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc return false; } EventRegistrationToken token; - udpSocket()->add_MessageReceived(Callback(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &token); socketDescriptor = qintptr(socket.Detach()); + udpSocket()->add_MessageReceived(Callback(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &token); return true; } default: From 3006bd2d44298babd1339c3fc3a67ad0696bcefc Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Thu, 9 May 2013 11:42:05 +0200 Subject: [PATCH 30/89] Make QElapsedTimer default to invalid (and now non-POD). The practical uses of a POD QElapsedTimer are not really that clear, and the number of misuses of this API are quite high. Default the state to invalid to prevent against mistakes. [ChangeLog][QtCore][QElapsedTimer] Is no longer a POD. Change-Id: I267292acf2bfca7404e3e449dd04410441d7ce26 Reviewed-by: Lars Knoll --- src/corelib/tools/qelapsedtimer.cpp | 15 +++++++++++++-- src/corelib/tools/qelapsedtimer.h | 7 +++++++ src/corelib/tools/qelapsedtimer_generic.cpp | 2 ++ .../tools/qelapsedtimer/tst_qelapsedtimer.cpp | 10 ++-------- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/corelib/tools/qelapsedtimer.cpp b/src/corelib/tools/qelapsedtimer.cpp index 1da85fce96..08fc1cf5e2 100644 --- a/src/corelib/tools/qelapsedtimer.cpp +++ b/src/corelib/tools/qelapsedtimer.cpp @@ -201,6 +201,17 @@ QT_BEGIN_NAMESPACE \sa clockType(), isMonotonic() */ +/*! + \fn QElapsedTimer::QElapsedTimer() + \since 5.4 + + Constructs an invalid QElapsedTimer. A timer becomes valid once it has been + started. + + \sa isValid(), start() +*/ + + /*! \fn bool QElapsedTimer::operator ==(const QElapsedTimer &other) const @@ -230,8 +241,8 @@ void QElapsedTimer::invalidate() Q_DECL_NOTHROW } /*! - Returns \c false if this object was invalidated by a call to invalidate() and - has not been restarted since. + Returns \c false if the timer has never been started or invalidated by a + call to invalidate(). \sa invalidate(), start(), restart() */ diff --git a/src/corelib/tools/qelapsedtimer.h b/src/corelib/tools/qelapsedtimer.h index b06afe4ab4..7df5dec63a 100644 --- a/src/corelib/tools/qelapsedtimer.h +++ b/src/corelib/tools/qelapsedtimer.h @@ -57,6 +57,13 @@ public: MachAbsoluteTime, PerformanceCounter }; + + Q_DECL_CONSTEXPR QElapsedTimer() + : t1(Q_INT64_C(0x8000000000000000)) + , t2(Q_INT64_C(0x8000000000000000)) + { + } + static ClockType clockType() Q_DECL_NOTHROW; static bool isMonotonic() Q_DECL_NOTHROW; diff --git a/src/corelib/tools/qelapsedtimer_generic.cpp b/src/corelib/tools/qelapsedtimer_generic.cpp index 6324be00c0..7a52faa3c5 100644 --- a/src/corelib/tools/qelapsedtimer_generic.cpp +++ b/src/corelib/tools/qelapsedtimer_generic.cpp @@ -87,6 +87,8 @@ void QElapsedTimer::start() Q_DECL_NOTHROW and then starting the timer again with start(), but it does so in one single operation, avoiding the need to obtain the clock value twice. + Restarting the timer makes it valid again. + The following example illustrates how to use this function to calibrate a parameter to a slow operation (for example, an iteration count) so that this operation takes at least 250 milliseconds: diff --git a/tests/auto/corelib/tools/qelapsedtimer/tst_qelapsedtimer.cpp b/tests/auto/corelib/tools/qelapsedtimer/tst_qelapsedtimer.cpp index f2852f6a50..48e3745be4 100644 --- a/tests/auto/corelib/tools/qelapsedtimer/tst_qelapsedtimer.cpp +++ b/tests/auto/corelib/tools/qelapsedtimer/tst_qelapsedtimer.cpp @@ -48,12 +48,7 @@ static const int minResolution = 50; // the minimum resolution for the tests QDebug operator<<(QDebug s, const QElapsedTimer &t) { - union { - QElapsedTimer t; - struct { qint64 t1, t2; } i; - } copy; - copy.t = t; - s.nospace() << "(" << copy.i.t1 << ", " << copy.i.t2 << ")"; + s.nospace() << "(" << t.msecsSinceReference() << ")"; return s.space(); } @@ -81,8 +76,7 @@ void tst_QElapsedTimer::validity() { QElapsedTimer t; - t.invalidate(); - QVERIFY(!t.isValid()); + QVERIFY(!t.isValid()); // non-POD now, it should always start invalid t.start(); QVERIFY(t.isValid()); From 74303ad497ff0e3a9876d349e2ce2f67f08c0fbf Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 3 Sep 2014 09:40:01 +0200 Subject: [PATCH 31/89] QSwipeGestureRecognizer: Use qAbs() to check distances. Task-number: QTBUG-15768 Change-Id: Idc6c6687430365a015fb2c15f4e4dcae6a687f9f Reviewed-by: Shawn Rutledge --- src/widgets/kernel/qstandardgestures.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/kernel/qstandardgestures.cpp b/src/widgets/kernel/qstandardgestures.cpp index e57c3285d2..48c2ad9e47 100644 --- a/src/widgets/kernel/qstandardgestures.cpp +++ b/src/widgets/kernel/qstandardgestures.cpp @@ -335,7 +335,7 @@ QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state, d->swipeAngle = QLineF(p1.startScreenPos(), p1.screenPos()).angle(); static const int MoveThreshold = 50; - if (xDistance > MoveThreshold || yDistance > MoveThreshold) { + if (qAbs(xDistance) > MoveThreshold || qAbs(yDistance) > MoveThreshold) { // measure the distance to check if the direction changed d->lastPositions[0] = p1.screenPos().toPoint(); d->lastPositions[1] = p2.screenPos().toPoint(); From 4dae1a685c3d78fa0601e8490117e9a62336c398 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Wed, 3 Sep 2014 09:45:16 +0200 Subject: [PATCH 32/89] Use QPlatformTheme::SystemIconFallbackThemeName in static QString fallbackTheme() Instead of QPlatformTheme::SystemIconThemeName Change-Id: Id318944730cd1b8014380a972eb28fd8aab1f382 Reviewed-by: Friedemann Kleint --- src/gui/image/qiconloader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index 44935333fc..5a4460dea3 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -69,7 +69,7 @@ Q_GLOBAL_STATIC(QIconLoader, iconLoaderInstance) static QString fallbackTheme() { if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { - const QVariant themeHint = theme->themeHint(QPlatformTheme::SystemIconThemeName); + const QVariant themeHint = theme->themeHint(QPlatformTheme::SystemIconFallbackThemeName); if (themeHint.isValid()) return themeHint.toString(); } From 7af329fdf2ab25c38858fed8bb33e4fa0200766f Mon Sep 17 00:00:00 2001 From: Maks Naumov Date: Tue, 2 Sep 2014 22:53:35 +0300 Subject: [PATCH 33/89] Widgets: remove pointless assignments Assignment of a value was two times successively for same variable while the variable itself is not used between these assignments. Change-Id: I3c457e3af0505d32a64f6c8576b458cd15a951e5 Reviewed-by: Friedemann Kleint Reviewed-by: Marc Mutz --- src/widgets/util/qscroller.cpp | 5 ++--- src/widgets/widgets/qlineedit.cpp | 4 +--- src/widgets/widgets/qplaintextedit.cpp | 3 +-- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/widgets/util/qscroller.cpp b/src/widgets/util/qscroller.cpp index 235cbc7865..abbba87039 100644 --- a/src/widgets/util/qscroller.cpp +++ b/src/widgets/util/qscroller.cpp @@ -746,9 +746,8 @@ void QScroller::ensureVisible(const QRectF &rect, qreal xmargin, qreal ymargin, return; // -- calculate the current pos (or the position after the current scroll) - QPointF startPos = d->contentPosition + d->overshootPosition; - startPos = QPointF(d->scrollingSegmentsEndPos(Qt::Horizontal), - d->scrollingSegmentsEndPos(Qt::Vertical)); + QPointF startPos(d->scrollingSegmentsEndPos(Qt::Horizontal), + d->scrollingSegmentsEndPos(Qt::Vertical)); QRectF marginRect(rect.x() - xmargin, rect.y() - ymargin, rect.width() + 2 * xmargin, rect.height() + 2 * ymargin); diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index b6b7ffb1a2..461be744ff 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -1877,14 +1877,12 @@ void QLineEdit::paintEvent(QPaintEvent *) { Q_D(QLineEdit); QPainter p(this); - - QRect r = rect(); QPalette pal = palette(); QStyleOptionFrameV2 panel; initStyleOption(&panel); style()->drawPrimitive(QStyle::PE_PanelLineEdit, &panel, &p, this); - r = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this); + QRect r = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this); r.setX(r.x() + d->effectiveLeftTextMargin()); r.setY(r.y() + d->topTextMargin); r.setRight(r.right() - d->effectiveRightTextMargin()); diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp index df13085dee..3f34a08b5e 100644 --- a/src/widgets/widgets/qplaintextedit.cpp +++ b/src/widgets/widgets/qplaintextedit.cpp @@ -690,10 +690,9 @@ void QPlainTextEditPrivate::ensureVisible(int position, bool center, bool forceC QRectF br = control->blockBoundingRect(block); if (!br.isValid()) return; - QRectF lr = br; QTextLine line = block.layout()->lineForTextPosition(position - block.position()); Q_ASSERT(line.isValid()); - lr = line.naturalTextRect().translated(br.topLeft()); + QRectF lr = line.naturalTextRect().translated(br.topLeft()); if (lr.bottom() >= visible.bottom() || (center && lr.top() < visible.top()) || forceCenter){ From 5cb21215c972e6ea406bd3e9c0461a0683edfa71 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 2 Sep 2014 15:10:29 +0200 Subject: [PATCH 34/89] Change a qFatal to a qWarning There are valid uses cases how to use Qt without installing any fonts (e.g. by using an application font), so let's make the warning non fatal. Task-number: QTBUG-29192 Change-Id: I5684331b687bef4b8a54be1f68303c80aa8d4372 Reviewed-by: Paul Olav Tvete Reviewed-by: Frederik Gladhorn --- src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp index 26ae0eb724..75359fbaa3 100644 --- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp @@ -96,8 +96,9 @@ void QBasicFontDatabase::populateFontDatabase() QString fontpath = fontDir(); if(!QFile::exists(fontpath)) { - qFatal("QFontDatabase: Cannot find font directory %s - is Qt installed correctly?", + qWarning("QFontDatabase: Cannot find font directory %s - is Qt installed correctly?", qPrintable(fontpath)); + return; } QDir dir(fontpath); From a02d798bbde691b8dd8f9c95aa54c9702cbad59a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeremy=20Lain=C3=A9?= Date: Wed, 3 Sep 2014 14:53:14 +0200 Subject: [PATCH 35/89] ssl: tighten QSslCertificateExtension tests This tightens tests performed on a certificate's extensions by checking isCritical() and isSupported() for all extensions. It also explicitly checks the keys when value() returns a QVariantMap. Change-Id: If51c55be25bbcd09cc3a6712ddfea2bf9a01360f Reviewed-by: Richard J. Moore --- .../ssl/qsslcertificate/tst_qsslcertificate.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp index cc90be00a2..138b1b5f15 100644 --- a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp +++ b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp @@ -1096,6 +1096,8 @@ void tst_QSslCertificate::extensions() QSslCertificateExtension unknown = extensions[unknown_idx]; QVERIFY(unknown.oid() == QStringLiteral("1.3.6.1.5.5.7.1.12")); QVERIFY(unknown.name() == QStringLiteral("1.3.6.1.5.5.7.1.12")); + QVERIFY(!unknown.isCritical()); + QVERIFY(!unknown.isSupported()); QByteArray unknownValue = QByteArray::fromHex( "3060A15EA05C305A305830561609696D6167652F6769663021301F300706052B0E03021A0414" \ @@ -1107,8 +1109,11 @@ void tst_QSslCertificate::extensions() QSslCertificateExtension aia = extensions[authority_info_idx]; QVERIFY(aia.oid() == QStringLiteral("1.3.6.1.5.5.7.1.1")); QVERIFY(aia.name() == QStringLiteral("authorityInfoAccess")); + QVERIFY(!aia.isCritical()); + QVERIFY(aia.isSupported()); QVariantMap aiaValue = aia.value().toMap(); + QCOMPARE(aiaValue.keys(), QList() << QStringLiteral("OCSP") << QStringLiteral("caIssuers")); QString ocsp = aiaValue[QStringLiteral("OCSP")].toString(); QString caIssuers = aiaValue[QStringLiteral("caIssuers")].toString(); @@ -1119,22 +1124,30 @@ void tst_QSslCertificate::extensions() QSslCertificateExtension basic = extensions[basic_constraints_idx]; QVERIFY(basic.oid() == QStringLiteral("2.5.29.19")); QVERIFY(basic.name() == QStringLiteral("basicConstraints")); + QVERIFY(!basic.isCritical()); + QVERIFY(basic.isSupported()); QVariantMap basicValue = basic.value().toMap(); + QCOMPARE(basicValue.keys(), QList() << QStringLiteral("ca")); QVERIFY(basicValue[QStringLiteral("ca")].toBool() == false); // Subject key identifier QSslCertificateExtension subjectKey = extensions[subject_key_idx]; QVERIFY(subjectKey.oid() == QStringLiteral("2.5.29.14")); QVERIFY(subjectKey.name() == QStringLiteral("subjectKeyIdentifier")); + QVERIFY(!subjectKey.isCritical()); + QVERIFY(subjectKey.isSupported()); QVERIFY(subjectKey.value().toString() == QStringLiteral("5F:90:23:CD:24:CA:52:C9:36:29:F0:7E:9D:B1:FE:08:E0:EE:69:F0")); // Authority key identifier QSslCertificateExtension authKey = extensions[auth_key_idx]; QVERIFY(authKey.oid() == QStringLiteral("2.5.29.35")); QVERIFY(authKey.name() == QStringLiteral("authorityKeyIdentifier")); + QVERIFY(!authKey.isCritical()); + QVERIFY(authKey.isSupported()); QVariantMap authValue = authKey.value().toMap(); + QCOMPARE(authValue.keys(), QList() << QStringLiteral("keyid")); QVERIFY(authValue[QStringLiteral("keyid")].toByteArray() == QByteArray("4e43c81d76ef37537a4ff2586f94f338e2d5bddf")); From 7e1e42cbf269c4fd5bbfa0411964bd14e5ae549c Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Wed, 3 Sep 2014 09:57:58 +0200 Subject: [PATCH 36/89] Android: Avoid deadlocks on suspend Get rid of the rendezvous at shutdown: the android thread does not need to wait for the GUI thread. Since the GUI thread frequently does blocking calls to the android thread, this fixes several known and potential deadlocks. Task-number: QTBUG-41072 Change-Id: Ia6fa8da026b1727e7352b22f4df4d72b63b8c847 Reviewed-by: BogDan Vatra Reviewed-by: Christian Stromme --- .../android/qandroideventdispatcher.cpp | 21 ++++++++++++------- .../android/qandroideventdispatcher.h | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/plugins/platforms/android/qandroideventdispatcher.cpp b/src/plugins/platforms/android/qandroideventdispatcher.cpp index 074ba71f80..ab5070af9d 100644 --- a/src/plugins/platforms/android/qandroideventdispatcher.cpp +++ b/src/plugins/platforms/android/qandroideventdispatcher.cpp @@ -55,20 +55,26 @@ QAndroidEventDispatcher::~QAndroidEventDispatcher() QAndroidEventDispatcherStopper::instance()->removeEventDispatcher(this); } +enum States {Running = 0, StopRequest = 1, Stopping = 2}; + void QAndroidEventDispatcher::start() { - if (m_stopRequest.testAndSetAcquire(1, 0)) { - m_dispatcherSemaphore.release(); + int prevState = m_stopRequest.fetchAndStoreAcquire(Running); + if (prevState == Stopping) { + m_semaphore.release(); wakeUp(); + } else if (prevState == Running) { + qWarning("Error: start without corresponding stop"); } + //else if prevState == StopRequest, no action needed } void QAndroidEventDispatcher::stop() { - if (m_stopRequest.testAndSetAcquire(0, 1)) { + if (m_stopRequest.testAndSetAcquire(Running, StopRequest)) wakeUp(); - m_stopperSemaphore.acquire(); - } + else + qWarning("Error: start/stop out of sync"); } void QAndroidEventDispatcher::goingToStop(bool stop) @@ -80,9 +86,8 @@ void QAndroidEventDispatcher::goingToStop(bool stop) int QAndroidEventDispatcher::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timespec *timeout) { - if (m_stopRequest.load() == 1) { - m_stopperSemaphore.release(); - m_dispatcherSemaphore.acquire(); + if (m_stopRequest.testAndSetAcquire(StopRequest, Stopping)) { + m_semaphore.acquire(); wakeUp(); } diff --git a/src/plugins/platforms/android/qandroideventdispatcher.h b/src/plugins/platforms/android/qandroideventdispatcher.h index 8d1bcf2122..284c5fd392 100644 --- a/src/plugins/platforms/android/qandroideventdispatcher.h +++ b/src/plugins/platforms/android/qandroideventdispatcher.h @@ -66,7 +66,7 @@ protected: private: QAtomicInt m_stopRequest; QAtomicInt m_goingToStop; - QSemaphore m_dispatcherSemaphore, m_stopperSemaphore; + QSemaphore m_semaphore; }; class QAndroidEventDispatcherStopper From f750979b70400e8681204b30282473aa6353ea06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeremy=20Lain=C3=A9?= Date: Wed, 3 Sep 2014 15:38:47 +0200 Subject: [PATCH 37/89] ssl: check critical certificate extensions This adds a test for a QSslCertificate containing extensions which are marked as critical. Change-Id: I314e1f5c9943bcad5d43129a97f9f834882dc6fb Reviewed-by: Richard J. Moore --- .../qsslcertificate/tst_qsslcertificate.cpp | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp index 138b1b5f15..56530acb14 100644 --- a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp +++ b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp @@ -111,6 +111,7 @@ private slots: void subjectAndIssuerAttributes(); void verify(); void extensions(); + void extensionsCritical(); void threadSafeConstMethods(); void version_data(); void version(); @@ -1150,7 +1151,53 @@ void tst_QSslCertificate::extensions() QCOMPARE(authValue.keys(), QList() << QStringLiteral("keyid")); QVERIFY(authValue[QStringLiteral("keyid")].toByteArray() == QByteArray("4e43c81d76ef37537a4ff2586f94f338e2d5bddf")); +} +void tst_QSslCertificate::extensionsCritical() +{ + QList certList = + QSslCertificate::fromPath(testDataDir + "/verify-certs/test-addons-mozilla-org-cert.pem"); + QVERIFY2(certList.count() > 0, "Please run this test from the source directory"); + + QSslCertificate cert = certList[0]; + QList extensions = cert.extensions(); +#ifdef Q_OS_WINRT + QEXPECT_FAIL("", "QTBUG-40884: WinRT API does not support extensions information", Abort); +#endif + QVERIFY(extensions.count() == 9); + + int basic_constraints_idx = -1; + int key_usage_idx = -1; + + for (int i=0; i < extensions.length(); ++i) { + QSslCertificateExtension ext = extensions[i]; + + if (ext.name() == QStringLiteral("basicConstraints")) + basic_constraints_idx = i; + if (ext.name() == QStringLiteral("keyUsage")) + key_usage_idx = i; + } + + QVERIFY(basic_constraints_idx != -1); + QVERIFY(key_usage_idx != -1); + + // Basic constraints + QSslCertificateExtension basic = extensions[basic_constraints_idx]; + QVERIFY(basic.oid() == QStringLiteral("2.5.29.19")); + QVERIFY(basic.name() == QStringLiteral("basicConstraints")); + QVERIFY(basic.isCritical()); + QVERIFY(basic.isSupported()); + + QVariantMap basicValue = basic.value().toMap(); + QCOMPARE(basicValue.keys(), QList() << QStringLiteral("ca")); + QVERIFY(basicValue[QStringLiteral("ca")].toBool() == false); + + // Key Usage + QSslCertificateExtension keyUsage = extensions[key_usage_idx]; + QVERIFY(keyUsage.oid() == QStringLiteral("2.5.29.15")); + QVERIFY(keyUsage.name() == QStringLiteral("keyUsage")); + QVERIFY(keyUsage.isCritical()); + QVERIFY(!keyUsage.isSupported()); } class TestThread : public QThread From ed418f91d525ccf43362d2bf04fe117d7ebb5570 Mon Sep 17 00:00:00 2001 From: Dimitar Asenov Date: Wed, 3 Sep 2014 14:43:25 +0200 Subject: [PATCH 38/89] Revert "Speed up the removal of items from a QGraphicsScene" This reverts commit bf2ec0183cb62034f2a4e700b7ab741371fcb106. That patch changed the way the linear index works in QGraphicsScene in order to speed up item removal. That patch occasionally rebuilt the index by recursively exploring all items in the scene, starting with the top level. Further testing revealved that in some circumstances, rebuilding the index in this way can be slow, thereby significantly slowing down the index compared to the unpatched version. The original patch only exists in the qt 5.4 branch and has not been released. Change-Id: I081dbcdcc86196ef382466c3e800a33eab9a5b79 Reviewed-by: Andreas Aardal Hanssen --- src/widgets/graphicsview/qgraphicsscene.h | 1 - .../qgraphicsscenelinearindex_p.h | 45 +++---------------- 2 files changed, 7 insertions(+), 39 deletions(-) diff --git a/src/widgets/graphicsview/qgraphicsscene.h b/src/widgets/graphicsview/qgraphicsscene.h index d95237baef..ba47d45d63 100644 --- a/src/widgets/graphicsview/qgraphicsscene.h +++ b/src/widgets/graphicsview/qgraphicsscene.h @@ -313,7 +313,6 @@ private: friend class QGraphicsEffect; friend class QGraphicsSceneIndex; friend class QGraphicsSceneIndexPrivate; - friend class QGraphicsSceneLinearIndex; friend class QGraphicsSceneBspTreeIndex; friend class QGraphicsSceneBspTreeIndexPrivate; friend class QGraphicsItemEffectSourcePrivate; diff --git a/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h b/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h index baf3de3755..7debcfb501 100644 --- a/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h +++ b/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h @@ -70,62 +70,31 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex Q_OBJECT public: - QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0) : QGraphicsSceneIndex(scene), m_itemsIsValid(true) + QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0) : QGraphicsSceneIndex(scene) { } QList items(Qt::SortOrder order = Qt::DescendingOrder) const - { - Q_UNUSED(order); - return validList(); - } + { Q_UNUSED(order); return m_items; } virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order) const { Q_UNUSED(rect); Q_UNUSED(order); - return validList(); + return m_items; } protected : virtual void clear() - { - m_items.clear(); - m_itemsIsValid = true; - } + { m_items.clear(); } virtual void addItem(QGraphicsItem *item) - { - if (m_itemsIsValid) - m_items << item; - } + { m_items << item; } virtual void removeItem(QGraphicsItem *item) - { - Q_UNUSED(item); - m_itemsIsValid = false; - } + { m_items.removeOne(item); } private: - mutable QList m_items; - mutable bool m_itemsIsValid; - - QList& validList() const - { - if (!m_itemsIsValid) - { - m_items.clear(); - - QList stack = scene()->d_func()->topLevelItems; - m_items << stack; - while (!stack.isEmpty()) - { - m_items << stack.last()->childItems(); - stack << stack.takeLast()->childItems(); - } - m_itemsIsValid = true; - } - return m_items; - } + QList m_items; }; #endif // QT_NO_GRAPHICSVIEW From 5b2f77c59839b3d110ca4bf7007e4d5ba513b078 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 3 Sep 2014 16:10:36 +0200 Subject: [PATCH 39/89] eglfs: Fix regression in config selection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During the introduction of context adoption support the config choosing got broken for context creation, at least for hooks that return a customized format in surfaceFormatFor(). The returned format is the one that needs to be passed to chooseConfig(), not the original. Change-Id: Iae203cbbf7b39c462386611dd3744f048116df13 Reviewed-by: Jørgen Lind --- src/plugins/platforms/eglfs/qeglfsintegration.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index d770ea763a..82269d07c6 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -120,13 +120,12 @@ QEGLPlatformContext *QEglFSIntegration::createContext(const QSurfaceFormat &form QVariant *nativeHandle) const { QEglFSContext *ctx; + QSurfaceFormat adjustedFormat = QEglFSHooks::hooks()->surfaceFormatFor(format); if (!nativeHandle || nativeHandle->isNull()) { - EGLConfig config = QEglFSIntegration::chooseConfig(display, format); - ctx = new QEglFSContext(QEglFSHooks::hooks()->surfaceFormatFor(format), shareContext, display, - &config, QVariant()); + EGLConfig config = QEglFSIntegration::chooseConfig(display, adjustedFormat); + ctx = new QEglFSContext(adjustedFormat, shareContext, display, &config, QVariant()); } else { - ctx = new QEglFSContext(QEglFSHooks::hooks()->surfaceFormatFor(format), shareContext, display, - 0, *nativeHandle); + ctx = new QEglFSContext(adjustedFormat, shareContext, display, 0, *nativeHandle); } *nativeHandle = QVariant::fromValue(QEGLNativeContext(ctx->eglContext(), display)); return ctx; From 633647334c14b263a0fcc7a5087bf1e2ea3e212a Mon Sep 17 00:00:00 2001 From: Dimitar Asenov Date: Tue, 2 Sep 2014 14:15:27 +0200 Subject: [PATCH 40/89] Speed up the removal of items from a QGraphicsScene When using a linear index, all items in a scene are stored in a QList. While adding new items is a constant operation, removal requires a traversal through the entire list. This is especially problematic when the scene contains millions of items and many of them are removed, which requires a linear search for each item, resulting in a very slow operation. Moreover, this behavior is actually inconsistent with the current documentation which states for the linear index: "Adding, moving and removing items, however, is done in constant time." With this change, the list is sorted once an item needs to be removed. The item to be removed is then found using binary search. To reduce the overhead of sorting the list is not sorted from scratch. First the newly inserted items are sorted and then the two parts of the list are merged. [ChangeLog][QtWidgets][QGraphicsScene] Speed up the removal of items when using the linear index. Change-Id: I28708622605d7fb0fac656df1f9b2f2fa3136759 Reviewed-by: Andreas Aardal Hanssen --- .../qgraphicsscenelinearindex_p.h | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h b/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h index 7debcfb501..5788818394 100644 --- a/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h +++ b/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h @@ -70,7 +70,7 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex Q_OBJECT public: - QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0) : QGraphicsSceneIndex(scene) + QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0) : QGraphicsSceneIndex(scene), m_numSortedElements(0) { } QList items(Qt::SortOrder order = Qt::DescendingOrder) const @@ -85,16 +85,35 @@ public: protected : virtual void clear() - { m_items.clear(); } + { + m_items.clear(); + m_numSortedElements = 0; + } virtual void addItem(QGraphicsItem *item) { m_items << item; } virtual void removeItem(QGraphicsItem *item) - { m_items.removeOne(item); } + { + // Sort m_items if needed + if (m_numSortedElements < m_items.size()) + { + std::sort(m_items.begin() + m_numSortedElements, m_items.end() ); + std::inplace_merge(m_items.begin(), m_items.begin() + m_numSortedElements, m_items.end()); + m_numSortedElements = m_items.size(); + } + + QList::iterator element = std::lower_bound(m_items.begin(), m_items.end(), item); + if (element != m_items.end() && *element == item) + { + m_items.erase(element); + --m_numSortedElements; + } + } private: QList m_items; + int m_numSortedElements; }; #endif // QT_NO_GRAPHICSVIEW From c68ef6d2c010da545c839ba669da011162828f76 Mon Sep 17 00:00:00 2001 From: Andy Nichols Date: Wed, 3 Sep 2014 16:40:19 +0200 Subject: [PATCH 41/89] DirectFB: Add QT_DIRECTFB_BLITTER_DEBUGPAINT environment variable This environment variable will paint an overlay on each paint command that is using the accelerated blitter path for DirectFB. This is useful when you want to assure that you are taking advantage of the DirectFB blitter. Change-Id: I6e374754825794daf9c1bf40bee2b963e752a8e9 Reviewed-by: Laszlo Agocs --- .../platforms/directfb/qdirectfbblitter.cpp | 71 +++++++++++++++++-- .../platforms/directfb/qdirectfbblitter.h | 3 + 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/src/plugins/platforms/directfb/qdirectfbblitter.cpp b/src/plugins/platforms/directfb/qdirectfbblitter.cpp index bc6e4d70e9..60a501f730 100644 --- a/src/plugins/platforms/directfb/qdirectfbblitter.cpp +++ b/src/plugins/platforms/directfb/qdirectfbblitter.cpp @@ -65,17 +65,22 @@ static QBlittable::Capabilities dfb_blitter_capabilities() QDirectFbBlitter::QDirectFbBlitter(const QSize &rect, IDirectFBSurface *surface) : QBlittable(rect, dfb_blitter_capabilities()) - , m_surface(surface) + , m_surface(surface) + , m_debugPaint(false) { m_surface->AddRef(m_surface.data()); DFBSurfaceCapabilities surfaceCaps; m_surface->GetCapabilities(m_surface.data(), &surfaceCaps); m_premult = (surfaceCaps & DSCAPS_PREMULTIPLIED); + if (qgetenv("QT_DIRECTFB_BLITTER_DEBUGPAINT").toInt()) + m_debugPaint = true; } QDirectFbBlitter::QDirectFbBlitter(const QSize &rect, bool alpha) - : QBlittable(rect, dfb_blitter_capabilities()), m_premult(false) + : QBlittable(rect, dfb_blitter_capabilities()) + , m_premult(false) + , m_debugPaint(false) { DFBSurfaceDescription surfaceDesc; memset(&surfaceDesc,0,sizeof(DFBSurfaceDescription)); @@ -95,6 +100,9 @@ QDirectFbBlitter::QDirectFbBlitter(const QSize &rect, bool alpha) surfaceDesc.pixelformat = QDirectFbBlitter::pixmapFormat(); } + if (qgetenv("QT_DIRECTFB_BLITTER_DEBUGPAINT").toInt()) + m_debugPaint = true; + IDirectFB *dfb = QDirectFbConvenience::dfbInterface(); dfb->CreateSurface(dfb , &surfaceDesc, m_surface.outPtr()); m_surface->Clear(m_surface.data(), 0, 0, 0, 0); @@ -165,6 +173,8 @@ void QDirectFbBlitter::alphaFillRect(const QRectF &rect, const QColor &color, QP result = m_surface->FillRectangle(m_surface.data(), x, y, w, h); if (result != DFB_OK) DirectFBError("QDirectFBBlitter::alphaFillRect()", result); + if (m_debugPaint) + drawDebugRect(QRect(x, y, w, h), QColor(Qt::blue)); } void QDirectFbBlitter::drawPixmapOpacity(const QRectF &rect, const QPixmap &pixmap, const QRectF &subrect, QPainter::CompositionMode cmode, qreal opacity) @@ -203,13 +213,19 @@ void QDirectFbBlitter::drawPixmapOpacity(const QRectF &rect, const QPixmap &pixm if (cmode == QPainter::CompositionMode_SourceOver) m_surface->SetDstBlendFunction(m_surface.data(), DSBF_INVSRCALPHA); - if ((sRect.w == dRect.w) && (sRect.h == dRect.h)) + if ((sRect.w == dRect.w) && (sRect.h == dRect.h)) { result = m_surface->Blit(m_surface.data(), s, &sRect, dRect.x, dRect.y); - else + if (result != DFB_OK) + DirectFBError("QDirectFBBlitter::drawPixmapOpacity()", result); + if (m_debugPaint) + drawDebugRect(QRect(dRect.x, dRect.y, sRect.w, sRect.h), QColor(Qt::green)); + } else { result = m_surface->StretchBlit(m_surface.data(), s, &sRect, &dRect); - - if (result != DFB_OK) - DirectFBError("QDirectFBBlitter::drawPixmapExtended()", result); + if (result != DFB_OK) + DirectFBError("QDirectFBBlitter::drawPixmapOpacity()", result); + if (m_debugPaint) + drawDebugRect(QRect(dRect.x, dRect.y, dRect.w, dRect.h), QColor(Qt::red)); + } } bool QDirectFbBlitter::drawCachedGlyphs(const QPaintEngineState *state, QFontEngine::GlyphFormat glyphFormat, int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions, QFontEngine *fontEngine) @@ -287,6 +303,12 @@ bool QDirectFbBlitter::drawCachedGlyphs(const QPaintEngineState *state, QFontEng m_surface->BatchBlit(m_surface.data(), cache->sourceSurface(), sourceRects.constData(), destPoints.constData(), nGlyphs); + if (m_debugPaint) { + for (int i = 0; i < nGlyphs; ++i) { + drawDebugRect(QRect(destPoints[i].x, destPoints[i].y, sourceRects[i].w, sourceRects[i].h), QColor(Qt::yellow)); + } + } + if (rs->clip && rs->clip->enabled) m_surface->SetClip(m_surface.data(), 0); return true; @@ -403,6 +425,41 @@ void QDirectFbBlitter::doUnlock() m_surface->Unlock(m_surface.data()); } +void QDirectFbBlitter::drawDebugRect(const QRect &rect, const QColor &color) +{ + int x, y, w, h; + DFBResult result; + + // check parameters + rect.getRect(&x, &y ,&w, &h); + if ((w <= 0) || (h <= 0)) return; + + m_surface->SetDrawingFlags(m_surface.data(), + DFBSurfaceDrawingFlags(m_premult ? (DSDRAW_BLEND | DSDRAW_SRC_PREMULTIPLY) : DSDRAW_BLEND)); + m_surface->SetPorterDuff(m_surface.data(), DSPD_SRC_OVER); + + // set color + m_surface->SetColor(m_surface.data(), color.red(), color.green(), color.blue(), 120); + + result = m_surface->DrawLine(m_surface.data(), x, y, x + w-1, y); + if (result != DFB_OK) + DirectFBError("QDirectFBBlitter::drawDebugRect()", result); + result = m_surface->DrawLine(m_surface.data(), x + w-1, y, x + w-1, y + h-1); + if (result != DFB_OK) + DirectFBError("QDirectFBBlitter::drawDebugRect()", result); + result = m_surface->DrawLine(m_surface.data(), x + w-1, y + h-1, x, y + h-1); + if (result != DFB_OK) + DirectFBError("QDirectFBBlitter::drawDebugRect()", result); + result = m_surface->DrawLine(m_surface.data(), x, y + h-1, x, y); + if (result != DFB_OK) + DirectFBError("QDirectFBBlitter::drawDebugRect()", result); + + m_surface->SetColor(m_surface.data(), color.red(), color.green(), color.blue(), 10); + result = m_surface->FillRectangle(m_surface.data(), x, y, w, h); + if (result != DFB_OK) + DirectFBError("QDirectFBBlitter::drawDebugRect()", result); +} + void QDirectFbTextureGlyphCache::resizeTextureData(int width, int height) { m_surface.reset();; diff --git a/src/plugins/platforms/directfb/qdirectfbblitter.h b/src/plugins/platforms/directfb/qdirectfbblitter.h index c60f0fac25..4fa432462f 100644 --- a/src/plugins/platforms/directfb/qdirectfbblitter.h +++ b/src/plugins/platforms/directfb/qdirectfbblitter.h @@ -79,7 +79,10 @@ protected: friend class QDirectFbConvenience; private: + void drawDebugRect(const QRect &rect, const QColor &color); + bool m_premult; + bool m_debugPaint; }; class QDirectFbBlitterPlatformPixmap : public QBlittablePlatformPixmap From bdb30abcd274d4fb1958e17ba8790e415a2ffe85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeremy=20Lain=C3=A9?= Date: Wed, 3 Sep 2014 10:44:02 +0200 Subject: [PATCH 42/89] ssl: add support for ASN.1 boolean values This adds support for reading and writing ASN.1 boolean values. It also adds an operator to test two ASN.1 elements for equality. Change-Id: I4a22cbf9808533d593fc59d27b63caaf650b1f57 Reviewed-by: Richard J. Moore --- src/network/ssl/qasn1element.cpp | 23 +++++++ src/network/ssl/qasn1element_p.h | 12 ++++ .../ssl/qasn1element/tst_qasn1element.cpp | 60 +++++++++++++++++++ 3 files changed, 95 insertions(+) diff --git a/src/network/ssl/qasn1element.cpp b/src/network/ssl/qasn1element.cpp index cd8ebed501..78fffbf793 100644 --- a/src/network/ssl/qasn1element.cpp +++ b/src/network/ssl/qasn1element.cpp @@ -155,6 +155,12 @@ void QAsn1Element::write(QDataStream &stream) const stream.writeRawData(mValue.data(), mValue.size()); } +QAsn1Element QAsn1Element::fromBool(bool val) +{ + return QAsn1Element(QAsn1Element::BooleanType, + QByteArray(1, val ? 0xff : 0x00)); +} + QAsn1Element QAsn1Element::fromInteger(unsigned int val) { QAsn1Element elem(QAsn1Element::IntegerType); @@ -199,6 +205,23 @@ QAsn1Element QAsn1Element::fromObjectId(const QByteArray &id) return elem; } +bool QAsn1Element::toBool(bool *ok) const +{ + if (*this == fromBool(true)) { + if (ok) + *ok = true; + return true; + } else if (*this == fromBool(false)) { + if (ok) + *ok = true; + return false; + } else { + if (ok) + *ok = false; + return false; + } +} + QDateTime QAsn1Element::toDateTime() const { if (mValue.endsWith('Z')) { diff --git a/src/network/ssl/qasn1element_p.h b/src/network/ssl/qasn1element_p.h index 949fd69875..b4445dacfd 100644 --- a/src/network/ssl/qasn1element_p.h +++ b/src/network/ssl/qasn1element_p.h @@ -64,6 +64,7 @@ class Q_AUTOTEST_EXPORT QAsn1Element public: enum ElementType { // universal + BooleanType = 0x01, IntegerType = 0x02, BitStringType = 0x03, OctetStringType = 0x04, @@ -91,10 +92,12 @@ public: bool read(const QByteArray &data); void write(QDataStream &data) const; + static QAsn1Element fromBool(bool val); static QAsn1Element fromInteger(unsigned int val); static QAsn1Element fromVector(const QVector &items); static QAsn1Element fromObjectId(const QByteArray &id); + bool toBool(bool *ok = 0) const; QDateTime toDateTime() const; QMultiMap toInfo() const; qint64 toInteger(bool *ok = 0) const; @@ -106,12 +109,21 @@ public: quint8 type() const { return mType; } QByteArray value() const { return mValue; } + friend inline bool operator==(const QAsn1Element &, const QAsn1Element &); + friend inline bool operator!=(const QAsn1Element &, const QAsn1Element &); + private: quint8 mType; QByteArray mValue; }; Q_DECLARE_TYPEINFO(QAsn1Element, Q_MOVABLE_TYPE); +inline bool operator==(const QAsn1Element &e1, const QAsn1Element &e2) +{ return e1.mType == e2.mType && e1.mValue == e2.mValue; } + +inline bool operator!=(const QAsn1Element &e1, const QAsn1Element &e2) +{ return e1.mType != e2.mType || e1.mValue != e2.mValue; } + QT_END_NAMESPACE #endif diff --git a/tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp b/tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp index 5fb4c28282..92b603473b 100644 --- a/tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp +++ b/tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp @@ -49,6 +49,10 @@ class tst_QAsn1Element : public QObject private slots: void emptyConstructor(); + void equals_data(); + void equals(); + void toBool_data(); + void toBool(); void dateTime_data(); void dateTime(); void integer_data(); @@ -68,6 +72,62 @@ void tst_QAsn1Element::emptyConstructor() QCOMPARE(elem.value(), QByteArray()); } +Q_DECLARE_METATYPE(QAsn1Element) + +void tst_QAsn1Element::equals_data() +{ + QTest::addColumn("a"); + QTest::addColumn("b"); + QTest::addColumn("equals"); + + QTest::newRow("equal") + << QAsn1Element(QAsn1Element::BooleanType, QByteArray("\0", 1)) + << QAsn1Element(QAsn1Element::BooleanType, QByteArray("\0", 1)) + << true; + QTest::newRow("different type") + << QAsn1Element(QAsn1Element::BooleanType, QByteArray("\0", 1)) + << QAsn1Element(QAsn1Element::IntegerType, QByteArray("\0", 1)) + << false; + QTest::newRow("different value") + << QAsn1Element(QAsn1Element::BooleanType, QByteArray("\0", 1)) + << QAsn1Element(QAsn1Element::BooleanType, QByteArray("\xff", 1)) + << false; +} + +void tst_QAsn1Element::equals() +{ + QFETCH(QAsn1Element, a); + QFETCH(QAsn1Element, b); + QFETCH(bool, equals); + QCOMPARE(a == b, equals); + QCOMPARE(a != b, !equals); +} + +void tst_QAsn1Element::toBool_data() +{ + QTest::addColumn("encoded"); + QTest::addColumn("value"); + QTest::addColumn("valid"); + + QTest::newRow("bad type") << QByteArray::fromHex("0201ff") << false << false; + QTest::newRow("bad value") << QByteArray::fromHex("010102") << false << false; + QTest::newRow("false") << QByteArray::fromHex("010100") << false << true; + QTest::newRow("true") << QByteArray::fromHex("0101ff") << true << true; +} + +void tst_QAsn1Element::toBool() +{ + QFETCH(QByteArray, encoded); + QFETCH(bool, value); + QFETCH(bool, valid); + + bool ok; + QAsn1Element elem; + QVERIFY(elem.read(encoded)); + QCOMPARE(elem.toBool(&ok), value); + QCOMPARE(ok, valid); +} + void tst_QAsn1Element::dateTime_data() { QTest::addColumn("encoded"); From 20ea0cbaba8fe38e1ab8c8240c3917af85f929f5 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Wed, 3 Sep 2014 10:34:28 +0300 Subject: [PATCH 43/89] direct2d: Work around ClearType rendering bug in translucent mode This switches the font rendering to use gray scale antialiasing when in translucent rendering mode. It does so by adding a flags argument to the paint engine, allowing for future expansion in communicating render hints from the device to the engine. Task-number: QTBUG-41002 Change-Id: I0265154716a12060e851b603a109e9c693f5e843 Reviewed-by: Louai Al-Khanji Reviewed-by: Friedemann Kleint --- .../direct2d/qwindowsdirect2dpaintdevice.cpp | 10 ++++++---- .../direct2d/qwindowsdirect2dpaintdevice.h | 4 +++- .../direct2d/qwindowsdirect2dpaintengine.cpp | 13 ++++++++----- .../direct2d/qwindowsdirect2dpaintengine.h | 9 ++++++++- .../direct2d/qwindowsdirect2dplatformpixmap.cpp | 8 +++++--- .../direct2d/qwindowsdirect2dplatformpixmap.h | 3 ++- .../platforms/direct2d/qwindowsdirect2dwindow.cpp | 4 ++++ 7 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp index f5f4923b2f..4bbe74b642 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp @@ -53,8 +53,9 @@ QT_BEGIN_NAMESPACE class QWindowsDirect2DPaintDevicePrivate { public: - QWindowsDirect2DPaintDevicePrivate(QWindowsDirect2DBitmap *bitmap, QInternal::PaintDeviceFlags f) - : engine(new QWindowsDirect2DPaintEngine(bitmap)) + QWindowsDirect2DPaintDevicePrivate(QWindowsDirect2DBitmap *bitmap, QInternal::PaintDeviceFlags f, + QWindowsDirect2DPaintEngine::Flags paintFlags) + : engine(new QWindowsDirect2DPaintEngine(bitmap, paintFlags)) , bitmap(bitmap) , flags(f) {} @@ -64,8 +65,9 @@ public: QInternal::PaintDeviceFlags flags; }; -QWindowsDirect2DPaintDevice::QWindowsDirect2DPaintDevice(QWindowsDirect2DBitmap *bitmap, QInternal::PaintDeviceFlags flags) - : d_ptr(new QWindowsDirect2DPaintDevicePrivate(bitmap, flags)) +QWindowsDirect2DPaintDevice::QWindowsDirect2DPaintDevice(QWindowsDirect2DBitmap *bitmap, QInternal::PaintDeviceFlags flags, + QWindowsDirect2DPaintEngine::Flags paintFlags) + : d_ptr(new QWindowsDirect2DPaintDevicePrivate(bitmap, flags, paintFlags)) { } diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h index c9d8607497..33cc536b6d 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h @@ -44,6 +44,7 @@ #include #include +#include "qwindowsdirect2dpaintengine.h" QT_BEGIN_NAMESPACE @@ -55,7 +56,8 @@ class QWindowsDirect2DPaintDevice : public QPaintDevice Q_DECLARE_PRIVATE(QWindowsDirect2DPaintDevice) public: - QWindowsDirect2DPaintDevice(QWindowsDirect2DBitmap *bitmap, QInternal::PaintDeviceFlags flags); + QWindowsDirect2DPaintDevice(QWindowsDirect2DBitmap *bitmap, QInternal::PaintDeviceFlags flags, + QWindowsDirect2DPaintEngine::Flags paintFlags = QWindowsDirect2DPaintEngine::NoFlag); QPaintEngine *paintEngine() const Q_DECL_OVERRIDE; int devType() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index a4e75f6571..1d28befe41 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp @@ -233,9 +233,10 @@ class QWindowsDirect2DPaintEnginePrivate : public QPaintEngineExPrivate { Q_DECLARE_PUBLIC(QWindowsDirect2DPaintEngine) public: - QWindowsDirect2DPaintEnginePrivate(QWindowsDirect2DBitmap *bm) + QWindowsDirect2DPaintEnginePrivate(QWindowsDirect2DBitmap *bm, QWindowsDirect2DPaintEngine::Flags flags) : bitmap(bm) , clipFlags(0) + , flags(flags) { pen.reset(); brush.reset(); @@ -247,6 +248,7 @@ public: unsigned int clipFlags; QStack pushedClips; + QWindowsDirect2DPaintEngine::Flags flags; QPointF currentBrushOrigin; @@ -868,8 +870,9 @@ public: const bool antiAlias = bool((q->state()->renderHints & QPainter::TextAntialiasing) && !(fontDef.styleStrategy & QFont::NoAntialias)); - dc()->SetTextAntialiasMode(antiAlias ? D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE - : D2D1_TEXT_ANTIALIAS_MODE_ALIASED); + const D2D1_TEXT_ANTIALIAS_MODE antialiasMode = (flags & QWindowsDirect2DPaintEngine::UseGrayscaleAntialiasing) + ? D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE : D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE; + dc()->SetTextAntialiasMode(antiAlias ? antialiasMode : D2D1_TEXT_ANTIALIAS_MODE_ALIASED); dc()->DrawGlyphRun(pos, &glyphRun, @@ -913,8 +916,8 @@ public: } }; -QWindowsDirect2DPaintEngine::QWindowsDirect2DPaintEngine(QWindowsDirect2DBitmap *bitmap) - : QPaintEngineEx(*(new QWindowsDirect2DPaintEnginePrivate(bitmap))) +QWindowsDirect2DPaintEngine::QWindowsDirect2DPaintEngine(QWindowsDirect2DBitmap *bitmap, Flags flags) + : QPaintEngineEx(*(new QWindowsDirect2DPaintEnginePrivate(bitmap, flags))) { QPaintEngine::PaintEngineFeatures unsupported = // As of 1.1 Direct2D does not natively support complex composition modes diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h index 1469d32876..4ed817b75f 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h @@ -59,7 +59,13 @@ class QWindowsDirect2DPaintEngine : public QPaintEngineEx Q_DECLARE_PRIVATE(QWindowsDirect2DPaintEngine) public: - QWindowsDirect2DPaintEngine(QWindowsDirect2DBitmap *bitmap); + enum Flag { + NoFlag = 0, + UseGrayscaleAntialiasing = 1, + }; + Q_DECLARE_FLAGS(Flags, Flag) + + QWindowsDirect2DPaintEngine(QWindowsDirect2DBitmap *bitmap, Flags flags); bool begin(QPaintDevice *pdev) Q_DECL_OVERRIDE; bool end() Q_DECL_OVERRIDE; @@ -119,6 +125,7 @@ private: void adjustForAliasing(QRectF *rect); void adjustForAliasing(QPointF *point); }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QWindowsDirect2DPaintEngine::Flags) QT_END_NAMESPACE diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp index d9f7c595ca..88b440f857 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp @@ -62,10 +62,11 @@ public: , devicePixelRatio(1.0) {} - QWindowsDirect2DPlatformPixmapPrivate(QWindowsDirect2DBitmap *bitmap) + QWindowsDirect2DPlatformPixmapPrivate(QWindowsDirect2DBitmap *bitmap, + QWindowsDirect2DPaintEngine::Flags flags) : owns_bitmap(false) , bitmap(bitmap) - , device(new QWindowsDirect2DPaintDevice(bitmap, QInternal::Pixmap)) + , device(new QWindowsDirect2DPaintDevice(bitmap, QInternal::Pixmap, flags)) , devicePixelRatio(1.0) {} @@ -91,9 +92,10 @@ QWindowsDirect2DPlatformPixmap::QWindowsDirect2DPlatformPixmap(PixelType pixelTy } QWindowsDirect2DPlatformPixmap::QWindowsDirect2DPlatformPixmap(QPlatformPixmap::PixelType pixelType, + QWindowsDirect2DPaintEngine::Flags flags, QWindowsDirect2DBitmap *bitmap) : QPlatformPixmap(pixelType, Direct2DClass) - , d_ptr(new QWindowsDirect2DPlatformPixmapPrivate(bitmap)) + , d_ptr(new QWindowsDirect2DPlatformPixmapPrivate(bitmap, flags)) { setSerialNumber(qt_d2dpixmap_serno++); diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h index 702ef7af92..69243abb1d 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h @@ -42,6 +42,7 @@ #ifndef QWINDOWSDIRECT2DPLATFORMPIXMAP_H #define QWINDOWSDIRECT2DPLATFORMPIXMAP_H +#include "qwindowsdirect2dpaintengine.h" #include #include @@ -57,7 +58,7 @@ public: QWindowsDirect2DPlatformPixmap(PixelType pixelType); // We do NOT take ownership of the bitmap through this constructor! - QWindowsDirect2DPlatformPixmap(PixelType pixelType, QWindowsDirect2DBitmap *bitmap); + QWindowsDirect2DPlatformPixmap(PixelType pixelType, QWindowsDirect2DPaintEngine::Flags flags, QWindowsDirect2DBitmap *bitmap); ~QWindowsDirect2DPlatformPixmap(); void resize(int width, int height) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp index 37987931b3..f739493c1a 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp @@ -308,7 +308,11 @@ void QWindowsDirect2DWindow::setupBitmap() m_bitmap.reset(new QWindowsDirect2DBitmap(backBufferBitmap.Get(), m_deviceContext.Get())); + QWindowsDirect2DPaintEngine::Flags flags = QWindowsDirect2DPaintEngine::NoFlag; + if (!m_directRendering) + flags |= QWindowsDirect2DPaintEngine::UseGrayscaleAntialiasing; QWindowsDirect2DPlatformPixmap *pp = new QWindowsDirect2DPlatformPixmap(QPlatformPixmap::PixmapType, + flags, m_bitmap.data()); m_pixmap.reset(new QPixmap(pp)); } From 38ea5428c4d84fc71aa80f4b312500cad8ccc8a5 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 3 Sep 2014 17:03:51 +0200 Subject: [PATCH 44/89] Enable QT_ANGLE_PLATFORM selection in dynamic builds Change-Id: I8ebe62ec1e024e8a0a0f9e8aeac6fb81b1095e72 Reviewed-by: Andrew Knight --- src/plugins/platforms/windows/qwindowseglcontext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 698a153533..886757d4ff 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -46,7 +46,7 @@ #include #include -#if defined(QT_OPENGL_ES_2_ANGLE) +#if defined(QT_OPENGL_ES_2_ANGLE) || defined(QT_OPENGL_DYNAMIC) # include #endif From 0bb2b6213518fdc56181b0ab1d6a6635c324dfc2 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 3 Sep 2014 16:38:25 +0200 Subject: [PATCH 45/89] windows: Fix dynamic opengl build Cannot call WGL or EGL functions directly anymore. Change-Id: I0d5c6217679d87a2092c945a9b841dfd7b6c299a Reviewed-by: Andrew Knight --- src/plugins/platforms/windows/qwindowseglcontext.cpp | 8 ++++---- src/plugins/platforms/windows/qwindowsglcontext.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 886757d4ff..e27b55da3e 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -541,12 +541,12 @@ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext, if (pbuffer == EGL_NO_SURFACE) return; - EGLDisplay prevDisplay = eglGetCurrentDisplay(); + EGLDisplay prevDisplay = QWindowsEGLStaticContext::libEGL.eglGetCurrentDisplay(); if (prevDisplay == EGL_NO_DISPLAY) // when no context is current prevDisplay = m_eglDisplay; - EGLContext prevContext = eglGetCurrentContext(); - EGLSurface prevSurfaceDraw = eglGetCurrentSurface(EGL_DRAW); - EGLSurface prevSurfaceRead = eglGetCurrentSurface(EGL_READ); + EGLContext prevContext = QWindowsEGLStaticContext::libEGL.eglGetCurrentContext(); + EGLSurface prevSurfaceDraw = QWindowsEGLStaticContext::libEGL.eglGetCurrentSurface(EGL_DRAW); + EGLSurface prevSurfaceRead = QWindowsEGLStaticContext::libEGL.eglGetCurrentSurface(EGL_READ); if (QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, pbuffer, pbuffer, m_eglContext)) { const GLubyte *s = QWindowsEGLStaticContext::libGLESv2.glGetString(GL_VERSION); diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index 1ed27f545d..869df26ef6 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -1207,8 +1207,8 @@ QWindowsGLContext::~QWindowsGLContext() bool QWindowsGLContext::updateObtainedParams(HDC hdc, int *obtainedSwapInterval) { - HGLRC prevContext = wglGetCurrentContext(); - HDC prevSurface = wglGetCurrentDC(); + HGLRC prevContext = QOpenGLStaticContext::opengl32.wglGetCurrentContext(); + HDC prevSurface = QOpenGLStaticContext::opengl32.wglGetCurrentDC(); if (!QOpenGLStaticContext::opengl32.wglMakeCurrent(hdc, m_renderingContext)) { qWarning("Failed to make context current."); From b9e3f5955154073ddb87b181f77aa46ae05269df Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 3 Sep 2014 14:50:27 +0200 Subject: [PATCH 46/89] QMdiSubWindow: Keep event filter on system menu over its lifetime. QMdiSubWindow::eventFilter() is supposed to close the sub window on a double click on the menu icon. However, it did not receive the double click event since it removed itself when the menu was hidden, which happened before the double click was delivered. Task-number: QTBUG-25179 Change-Id: I5e7fb02dda26ceab12e8b7554fc604066a0a3136 Reviewed-by: Shawn Rutledge --- src/widgets/widgets/qmdisubwindow.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/widgets/widgets/qmdisubwindow.cpp b/src/widgets/widgets/qmdisubwindow.cpp index 5521d866b2..5166c3cf38 100644 --- a/src/widgets/widgets/qmdisubwindow.cpp +++ b/src/widgets/widgets/qmdisubwindow.cpp @@ -1043,6 +1043,7 @@ void QMdiSubWindowPrivate::createSystemMenu() Q_ASSERT_X(q, "QMdiSubWindowPrivate::createSystemMenu", "You can NOT call this function before QMdiSubWindow's ctor"); systemMenu = new QMenu(q); + systemMenu->installEventFilter(q); const QStyle *style = q->style(); addToSystemMenu(RestoreAction, QMdiSubWindow::tr("&Restore"), SLOT(showNormal())); actions[RestoreAction]->setIcon(style->standardIcon(QStyle::SP_TitleBarNormalButton, 0, q)); @@ -2569,7 +2570,6 @@ void QMdiSubWindow::showSystemMenu() // Adjust x() with -menuwidth in reverse mode. if (isRightToLeft()) globalPopupPos -= QPoint(d->systemMenu->sizeHint().width(), 0); - d->systemMenu->installEventFilter(this); d->systemMenu->popup(globalPopupPos); } #endif // QT_NO_MENU @@ -2702,7 +2702,6 @@ bool QMdiSubWindow::eventFilter(QObject *object, QEvent *event) QMouseEvent *mouseEvent = static_cast(event); d->hoveredSubControl = d->getSubControl(mapFromGlobal(mouseEvent->globalPos())); } else if (event->type() == QEvent::Hide) { - d->systemMenu->removeEventFilter(this); d->activeSubControl = QStyle::SC_None; update(QRegion(0, 0, width(), d->titleBarHeight())); } From 105fa5b5d9e876bd0da962f2a91ccd83d8bea459 Mon Sep 17 00:00:00 2001 From: Samuel Nevala Date: Wed, 3 Sep 2014 13:27:27 +0300 Subject: [PATCH 47/89] Respect android:windowSoftInputMode in manifest. Read and store softInputMode set at AndroidManifest.xml on QtActivityDelegate. When showSoftwareKeyboard is requested setSoftInputMode for main window if softInputMode is not defined fall back to old behavior. Change-Id: I71cb27d4bdb4ae4e3c2a0706560173703a2f5a50 Task-number: QTBUG-34401 Reviewed-by: BogDan Vatra Reviewed-by: Paul Olav Tvete --- .../qt5/android/QtActivityDelegate.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 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 01aa55c19e..c85104b11e 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -45,6 +45,7 @@ package org.qtproject.qt5.android; import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; @@ -110,6 +111,7 @@ public class QtActivityDelegate private String m_mainLib; private long m_metaState; private int m_lastChar = 0; + private int m_softInputMode = 0; private boolean m_fullScreen = false; private boolean m_started = false; private HashMap m_surfaces = null; @@ -246,10 +248,12 @@ public class QtActivityDelegate if (m_imm == null) return; - if (height > m_layout.getHeight() * 2 / 3) - m_activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); - else + if (m_softInputMode == 0 && height > m_layout.getHeight() * 2 / 3) + m_activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + else if (m_softInputMode == 0) m_activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); + else + m_activity.getWindow().setSoftInputMode(m_softInputMode); int initialCapsMode = 0; int imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_DONE; @@ -474,6 +478,12 @@ public class QtActivityDelegate else m_applicationParameters = ""; + try { + m_softInputMode = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(), 0).softInputMode; + } catch (Exception e) { + e.printStackTrace(); + } + return true; } From f4ae4f41b06d61f32dbef3cac90e8e3b187ee378 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 1 Sep 2014 16:25:14 +0200 Subject: [PATCH 48/89] hellowindow: Set all the state for each frame MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trying to be smart and minimizing the amount of GL calls per frame to provide a good example was a mistake (in a way): There are components, like the eglfs mouse cursor, that change the context state. To make sure the example work in these cases, set the state upon each frame. Change-Id: Ief1fd7bbb0fb1955a64dac97a071b7a3d9d506d4 Reviewed-by: Jørgen Lind --- examples/opengl/hellowindow/hellowindow.cpp | 27 ++++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/examples/opengl/hellowindow/hellowindow.cpp b/examples/opengl/hellowindow/hellowindow.cpp index da31fee920..57eb111edb 100644 --- a/examples/opengl/hellowindow/hellowindow.cpp +++ b/examples/opengl/hellowindow/hellowindow.cpp @@ -147,6 +147,21 @@ void Renderer::render() f->glViewport(0, 0, viewSize.width() * surface->devicePixelRatio(), viewSize.height() * surface->devicePixelRatio()); f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + f->glClearColor(0.1f, 0.1f, 0.2f, 1.0f); + f->glFrontFace(GL_CW); + f->glCullFace(GL_FRONT); + f->glEnable(GL_CULL_FACE); + f->glEnable(GL_DEPTH_TEST); + + m_program->bind(); + m_vbo.bind(); + + m_program->enableAttributeArray(vertexAttr); + m_program->enableAttributeArray(normalAttr); + m_program->setAttributeBuffer(vertexAttr, GL_FLOAT, 0, 3); + const int verticesSize = vertices.count() * 3 * sizeof(GLfloat); + m_program->setAttributeBuffer(normalAttr, GL_FLOAT, verticesSize, 3); + QMatrix4x4 modelview; modelview.rotate(m_fAngle, 0.0f, 1.0f, 0.0f); modelview.rotate(m_fAngle, 1.0f, 0.0f, 0.0f); @@ -212,18 +227,6 @@ void Renderer::initialize() m_vbo.allocate(verticesSize * 2); m_vbo.write(0, vertices.constData(), verticesSize); m_vbo.write(verticesSize, normals.constData(), verticesSize); - - QOpenGLFunctions *f = m_context->functions(); - f->glClearColor(0.1f, 0.1f, 0.2f, 1.0f); - f->glFrontFace(GL_CW); - f->glCullFace(GL_FRONT); - f->glEnable(GL_CULL_FACE); - f->glEnable(GL_DEPTH_TEST); - - m_program->enableAttributeArray(vertexAttr); - m_program->enableAttributeArray(normalAttr); - m_program->setAttributeBuffer(vertexAttr, GL_FLOAT, 0, 3); - m_program->setAttributeBuffer(normalAttr, GL_FLOAT, verticesSize, 3); } void Renderer::createGeometry() From 52f859604ddc12d273111644bbfd78f7f8a030ea Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 3 Jul 2014 11:19:21 +0200 Subject: [PATCH 49/89] Accessibility: Improve line boundary helper functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These functions are supposed to make it easy for third parties (and QLineEdit) to implement the textAt/Before/AfterOffset functions. Before the functions were ignoring newlines completely and thus only somewhat useful. Change-Id: I7136b9502a7fa6f8ad9ad7236761a34c1a7fd4da Reviewed-by: Jan Arve Sæther --- src/gui/accessible/qaccessible.cpp | 96 +++++++++- src/widgets/accessible/simplewidgets.cpp | 6 - .../other/qaccessibility/accessiblewidgets.h | 167 ++++++++++++++++++ .../other/qaccessibility/qaccessibility.pro | 3 +- .../qaccessibility/tst_qaccessibility.cpp | 141 ++++++++++----- 5 files changed, 357 insertions(+), 56 deletions(-) create mode 100644 tests/auto/other/qaccessibility/accessiblewidgets.h diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index c01834a744..50f023ec78 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -1911,17 +1911,66 @@ QDebug operator<<(QDebug d, const QAccessibleEvent &ev) The \a endOffset is the first character that will not be returned. */ +/*! + \internal + Helper for finding line breaks in textBeforeOffset/textAtOffset/textAfterOffset. + \a beforeAtAfter is the line we look for. -1 for before, 0 for at and 1 for after. +*/ +static QString textLineBoundary(int beforeAtAfter, const QString &text, int offset, int *startOffset, int *endOffset) +{ + Q_ASSERT(beforeAtAfter >= -1 && beforeAtAfter <= 1); + Q_ASSERT(*startOffset == -1 && *endOffset == -1); + int length = text.length(); + Q_ASSERT(offset >= 0 && offset <= length); + + // move offset into the right range (if asking for line before or after + if (beforeAtAfter == 1) { + offset = text.indexOf(QChar::LineFeed, qMin(offset, length - 1)); + if (offset < 0) + return QString(); // after the last line comes nothing + ++offset; // move after the newline + } else if (beforeAtAfter == -1) { + offset = text.lastIndexOf(QChar::LineFeed, qMax(offset - 1, 0)); + if (offset < 0) + return QString(); // before first line comes nothing + } + + if (offset > 0) + *startOffset = text.lastIndexOf(QChar::LineFeed, offset - 1); + ++*startOffset; // move to the char after the newline (0 if lastIndexOf returned -1) + + *endOffset = text.indexOf(QChar::LineFeed, qMin(offset, length - 1)) + 1; // include newline char + if (*endOffset <= 0 || *endOffset > length) + *endOffset = length; // if the text doesn't end with a newline it ends at length + + return text.mid(*startOffset, *endOffset - *startOffset); +} + /*! Returns the text item of type \a boundaryType that is close to offset \a offset and sets \a startOffset and \a endOffset values to the start and end positions of that item; returns an empty string if there is no such an item. Sets \a startOffset and \a endOffset values to -1 on error. + + This default implementation is provided for small text edits. A word processor or + text editor should provide their own efficient implementations. This function makes no + distinction between paragraphs and lines. + + \note this function can not take the cursor position into account. By convention + an \a offset of -2 means that this function should use the cursor position as offset. + Thus an offset of -2 must be converted to the cursor position before calling this + function. + An offset of -1 is used for the text length and custom implementations of this function + have to return the result as if the length was passed in as offset. */ QString QAccessibleTextInterface::textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType, int *startOffset, int *endOffset) const { const QString txt = text(0, characterCount()); + if (offset == -1) + offset = txt.length(); + *startOffset = *endOffset = -1; if (txt.isEmpty() || offset <= 0 || offset > txt.length()) return QString(); @@ -1937,7 +1986,11 @@ QString QAccessibleTextInterface::textBeforeOffset(int offset, QAccessible::Text case QAccessible::SentenceBoundary: type = QTextBoundaryFinder::Sentence; break; - default: + case QAccessible::LineBoundary: + case QAccessible::ParagraphBoundary: + // Lines can not use QTextBoundaryFinder since Line there means any potential line-break. + return textLineBoundary(-1, txt, offset, startOffset, endOffset); + case QAccessible::NoBoundary: // return empty, this function currently only supports single lines, so there can be no line before return QString(); } @@ -1969,12 +2022,26 @@ QString QAccessibleTextInterface::textBeforeOffset(int offset, QAccessible::Text and sets \a startOffset and \a endOffset values to the start and end positions of that item; returns an empty string if there is no such an item. Sets \a startOffset and \a endOffset values to -1 on error. + + This default implementation is provided for small text edits. A word processor or + text editor should provide their own efficient implementations. This function makes no + distinction between paragraphs and lines. + + \note this function can not take the cursor position into account. By convention + an \a offset of -2 means that this function should use the cursor position as offset. + Thus an offset of -2 must be converted to the cursor position before calling this + function. + An offset of -1 is used for the text length and custom implementations of this function + have to return the result as if the length was passed in as offset. */ QString QAccessibleTextInterface::textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType, int *startOffset, int *endOffset) const { const QString txt = text(0, characterCount()); + if (offset == -1) + offset = txt.length(); + *startOffset = *endOffset = -1; if (txt.isEmpty() || offset < 0 || offset >= txt.length()) return QString(); @@ -1990,7 +2057,11 @@ QString QAccessibleTextInterface::textAfterOffset(int offset, QAccessible::TextB case QAccessible::SentenceBoundary: type = QTextBoundaryFinder::Sentence; break; - default: + case QAccessible::LineBoundary: + case QAccessible::ParagraphBoundary: + // Lines can not use QTextBoundaryFinder since Line there means any potential line-break. + return textLineBoundary(1, txt, offset, startOffset, endOffset); + case QAccessible::NoBoundary: // return empty, this function currently only supports single lines, so there can be no line after return QString(); } @@ -2033,12 +2104,26 @@ QString QAccessibleTextInterface::textAfterOffset(int offset, QAccessible::TextB and sets \a startOffset and \a endOffset values to the start and end positions of that item; returns an empty string if there is no such an item. Sets \a startOffset and \a endOffset values to -1 on error. + + This default implementation is provided for small text edits. A word processor or + text editor should provide their own efficient implementations. This function makes no + distinction between paragraphs and lines. + + \note this function can not take the cursor position into account. By convention + an \a offset of -2 means that this function should use the cursor position as offset. + Thus an offset of -2 must be converted to the cursor position before calling this + function. + An offset of -1 is used for the text length and custom implementations of this function + have to return the result as if the length was passed in as offset. */ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType, int *startOffset, int *endOffset) const { const QString txt = text(0, characterCount()); + if (offset == -1) + offset = txt.length(); + *startOffset = *endOffset = -1; if (txt.isEmpty() || offset < 0 || offset > txt.length()) return QString(); @@ -2057,8 +2142,11 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun case QAccessible::SentenceBoundary: type = QTextBoundaryFinder::Sentence; break; - default: - // return the whole line + case QAccessible::LineBoundary: + case QAccessible::ParagraphBoundary: + // Lines can not use QTextBoundaryFinder since Line there means any potential line-break. + return textLineBoundary(0, txt, offset, startOffset, endOffset); + case QAccessible::NoBoundary: *startOffset = 0; *endOffset = txt.length(); return txt; diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp index e8827f4537..2064914683 100644 --- a/src/widgets/accessible/simplewidgets.cpp +++ b/src/widgets/accessible/simplewidgets.cpp @@ -729,8 +729,6 @@ QString QAccessibleLineEdit::textBeforeOffset(int offset, QAccessible::TextBound *startOffset = *endOffset = -1; return QString(); } - if (offset == -1) - offset = lineEdit()->text().length(); if (offset == -2) offset = cursorPosition(); return QAccessibleTextInterface::textBeforeOffset(offset, boundaryType, startOffset, endOffset); @@ -743,8 +741,6 @@ QString QAccessibleLineEdit::textAfterOffset(int offset, QAccessible::TextBounda *startOffset = *endOffset = -1; return QString(); } - if (offset == -1) - offset = lineEdit()->text().length(); if (offset == -2) offset = cursorPosition(); return QAccessibleTextInterface::textAfterOffset(offset, boundaryType, startOffset, endOffset); @@ -757,8 +753,6 @@ QString QAccessibleLineEdit::textAtOffset(int offset, QAccessible::TextBoundaryT *startOffset = *endOffset = -1; return QString(); } - if (offset == -1) - offset = lineEdit()->text().length(); if (offset == -2) offset = cursorPosition(); return QAccessibleTextInterface::textAtOffset(offset, boundaryType, startOffset, endOffset); diff --git a/tests/auto/other/qaccessibility/accessiblewidgets.h b/tests/auto/other/qaccessibility/accessiblewidgets.h new file mode 100644 index 0000000000..c15cd43f85 --- /dev/null +++ b/tests/auto/other/qaccessibility/accessiblewidgets.h @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 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 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef ACCESSIBLEWIDGETS_H +#define ACCESSIBLEWIDGETS_H + +#include +#include + +class QtTestAccessibleWidget: public QWidget +{ + Q_OBJECT +public: + QtTestAccessibleWidget(QWidget *parent, const char *name): QWidget(parent) + { + setObjectName(name); + } +}; + +class QtTestAccessibleWidgetIface: public QAccessibleWidget +{ +public: + QtTestAccessibleWidgetIface(QtTestAccessibleWidget *w): QAccessibleWidget(w) {} + QString text(QAccessible::Text t) const Q_DECL_OVERRIDE + { + if (t == QAccessible::Help) + return QString::fromLatin1("Help yourself"); + return QAccessibleWidget::text(t); + } + static QAccessibleInterface *ifaceFactory(const QString &key, QObject *o) + { + if (key == "QtTestAccessibleWidget") + return new QtTestAccessibleWidgetIface(static_cast(o)); + return 0; + } +}; + +class QtTestAccessibleWidgetSubclass: public QtTestAccessibleWidget +{ + Q_OBJECT +public: + QtTestAccessibleWidgetSubclass(QWidget *parent, const char *name): QtTestAccessibleWidget(parent, name) + {} +}; + + +class KFooButton: public QPushButton +{ + Q_OBJECT +public: + KFooButton(const QString &text, QWidget* parent = 0) + : QPushButton(text, parent) + {} +}; + + +class CustomTextWidget : public QWidget +{ + Q_OBJECT +public: + int cursorPosition; + QString text; +}; + +class CustomTextWidgetIface: public QAccessibleWidget, public QAccessibleTextInterface +{ +public: + static QAccessibleInterface *ifaceFactory(const QString &key, QObject *o) + { + if (key == "CustomTextWidget") + return new CustomTextWidgetIface(static_cast(o)); + return 0; + } + CustomTextWidgetIface(CustomTextWidget *w): QAccessibleWidget(w) {} + void *interface_cast(QAccessible::InterfaceType t) { + if (t == QAccessible::TextInterface) + return static_cast(this); + return 0; + } + + // this is mostly to test the base implementation for textBefore/At/After + QString text(QAccessible::Text t) const Q_DECL_OVERRIDE + { + if (t == QAccessible::Value) + return textWidget()->text; + return QAccessibleWidget::text(t); + } + + QString textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType, int *startOffset, int *endOffset) const + { + if (offset == -2) + offset = textWidget()->cursorPosition; + return QAccessibleTextInterface::textBeforeOffset(offset, boundaryType, startOffset, endOffset); + } + QString textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType, int *startOffset, int *endOffset) const + { + if (offset == -2) + offset = textWidget()->cursorPosition; + return QAccessibleTextInterface::textAtOffset(offset, boundaryType, startOffset, endOffset); + } + QString textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType, int *startOffset, int *endOffset) const + { + if (offset == -2) + offset = textWidget()->cursorPosition; + return QAccessibleTextInterface::textAfterOffset(offset, boundaryType, startOffset, endOffset); + } + + void selection(int, int *startOffset, int *endOffset) const Q_DECL_OVERRIDE + { *startOffset = *endOffset = -1; } + int selectionCount() const Q_DECL_OVERRIDE { return 0; } + void addSelection(int, int) Q_DECL_OVERRIDE {} + void removeSelection(int) Q_DECL_OVERRIDE {} + void setSelection(int, int, int) Q_DECL_OVERRIDE {} + int cursorPosition() const Q_DECL_OVERRIDE { return textWidget()->cursorPosition; } + void setCursorPosition(int position) Q_DECL_OVERRIDE { textWidget()->cursorPosition = position; } + QString text(int startOffset, int endOffset) const Q_DECL_OVERRIDE { return textWidget()->text.mid(startOffset, endOffset); } + int characterCount() const Q_DECL_OVERRIDE { return textWidget()->text.length(); } + QRect characterRect(int) const Q_DECL_OVERRIDE { return QRect(); } + int offsetAtPoint(const QPoint &) const Q_DECL_OVERRIDE { return 0; } + void scrollToSubstring(int, int) Q_DECL_OVERRIDE {} + QString attributes(int, int *, int *) const Q_DECL_OVERRIDE + { return QString(); } + +private: + CustomTextWidget *textWidget() const { return qobject_cast(widget()); } +}; + +#endif // ACCESSIBLEWIDGETS_H diff --git a/tests/auto/other/qaccessibility/qaccessibility.pro b/tests/auto/other/qaccessibility/qaccessibility.pro index e6c5bb1149..8d445437df 100644 --- a/tests/auto/other/qaccessibility/qaccessibility.pro +++ b/tests/auto/other/qaccessibility/qaccessibility.pro @@ -2,7 +2,8 @@ CONFIG += testcase TARGET = tst_qaccessibility requires(contains(QT_CONFIG,accessibility)) QT += testlib core-private gui-private widgets-private -SOURCES += tst_qaccessibility.cpp +SOURCES += tst_qaccessibility.cpp +HEADERS += accessiblewidgets.h unix:!mac:LIBS+=-lm diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index 2353d5b5b5..ac90f6ea72 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -75,6 +75,8 @@ #include +#include "accessiblewidgets.h" + // Make a widget frameless to prevent size constraints of title bars // from interfering (Windows). static inline void setFrameless(QWidget *w) @@ -266,6 +268,8 @@ private slots: void lineEditTest(); void lineEditTextFunctions_data(); void lineEditTextFunctions(); + void textInterfaceTest_data(); + void textInterfaceTest(); void groupBoxTest(); void dialogButtonBoxTest(); void dialTest(); @@ -395,43 +399,6 @@ void tst_QAccessibility::eventTest() QTestAccessibility::clearEvents(); } - -class QtTestAccessibleWidget: public QWidget -{ - Q_OBJECT -public: - QtTestAccessibleWidget(QWidget *parent, const char *name): QWidget(parent) - { - setObjectName(name); - } -}; - -class QtTestAccessibleWidgetIface: public QAccessibleWidget -{ -public: - QtTestAccessibleWidgetIface(QtTestAccessibleWidget *w): QAccessibleWidget(w) {} - QString text(QAccessible::Text t) const - { - if (t == QAccessible::Help) - return QString::fromLatin1("Help yourself"); - return QAccessibleWidget::text(t); - } - static QAccessibleInterface *ifaceFactory(const QString &key, QObject *o) - { - if (key == "QtTestAccessibleWidget") - return new QtTestAccessibleWidgetIface(static_cast(o)); - return 0; - } -}; - -class QtTestAccessibleWidgetSubclass: public QtTestAccessibleWidget -{ - Q_OBJECT -public: - QtTestAccessibleWidgetSubclass(QWidget *parent, const char *name): QtTestAccessibleWidget(parent, name) - {} -}; - void tst_QAccessibility::customWidget() { { @@ -491,14 +458,6 @@ void tst_QAccessibility::deletedWidget() // fixme: QVERIFY(!iface->isValid()); } -class KFooButton: public QPushButton -{ - Q_OBJECT -public: - KFooButton(const QString &text, QWidget* parent = 0) : QPushButton(text, parent) - {} -}; - void tst_QAccessibility::subclassedWidget() { KFooButton button("Ploink", 0); @@ -2381,6 +2340,98 @@ void tst_QAccessibility::lineEditTextFunctions() QTestAccessibility::clearEvents(); } +void tst_QAccessibility::textInterfaceTest_data() +{ + lineEditTextFunctions_data(); + QString hello = QStringLiteral("hello\nworld\nend"); + QTest::newRow("multi line at 0") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 0 << 0 << 6 << "hello\n"; + QTest::newRow("multi line at 1") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 1 << 0 << 6 << "hello\n"; + QTest::newRow("multi line at 2") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 2 << 0 << 6 << "hello\n"; + QTest::newRow("multi line at 5") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 5 << 0 << 6 << "hello\n"; + QTest::newRow("multi line at 6") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 6 << 6 << 12 << "world\n"; + QTest::newRow("multi line at 7") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 7 << 6 << 12 << "world\n"; + QTest::newRow("multi line at 8") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 8 << 6 << 12 << "world\n"; + QTest::newRow("multi line at 10") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 10 << 6 << 12 << "world\n"; + QTest::newRow("multi line at 11") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 11 << 6 << 12 << "world\n"; + QTest::newRow("multi line at 12") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 12 << 12 << 15 << "end"; + + QTest::newRow("multi line before 0") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 0 << -1 << -1 << ""; + QTest::newRow("multi line before 1") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 1 << -1 << -1 << ""; + QTest::newRow("multi line before 2") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 2 << -1 << -1 << ""; + QTest::newRow("multi line before 5") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 5 << -1 << -1 << ""; + QTest::newRow("multi line before 6") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 6 << 0 << 6 << "hello\n"; + QTest::newRow("multi line before 7") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 7 << 0 << 6 << "hello\n"; + QTest::newRow("multi line before 8") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 8 << 0 << 6 << "hello\n"; + QTest::newRow("multi line before 10") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 10 << 0 << 6 << "hello\n"; + QTest::newRow("multi line before 11") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 11 << 0 << 6 << "hello\n"; + QTest::newRow("multi line before 12") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 12 << 6 << 12 << "world\n"; + + QTest::newRow("multi line after 0") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 0 << 6 << 12 << "world\n"; + QTest::newRow("multi line after 1") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 1 << 6 << 12 << "world\n"; + QTest::newRow("multi line after 2") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 2 << 6 << 12 << "world\n"; + QTest::newRow("multi line after 5") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 5 << 6 << 12 << "world\n"; + QTest::newRow("multi line after 6") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 6 << 12 << 15 << "end"; + QTest::newRow("multi line after 7") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 7 << 12 << 15 << "end"; + QTest::newRow("multi line after 8") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 8 << 12 << 15 << "end"; + QTest::newRow("multi line after 10") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 10 << 12 << 15 << "end"; + QTest::newRow("multi line after 11") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 11 << 12 << 15 << "end"; + QTest::newRow("multi line after 12") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 12 << -1 << -1 << ""; + + QTest::newRow("before 4 \\nFoo\\n") << QStringLiteral("\nFoo\n") << 0 << (int) QAccessible::LineBoundary << 0 << 4 << 0 << 1 << "\n"; + QTest::newRow("at 4 \\nFoo\\n") << QStringLiteral("\nFoo\n") << 1 << (int) QAccessible::LineBoundary << 0 << 4 << 1 << 5 << "Foo\n"; + QTest::newRow("after 4 \\nFoo\\n") << QStringLiteral("\nFoo\n") << 2 << (int) QAccessible::LineBoundary << 0 << 4 << 5 << 5 << ""; + QTest::newRow("before 4 Foo\\nBar\\n") << QStringLiteral("Foo\nBar\n") << 0 << (int) QAccessible::LineBoundary << 0 << 7 << 0 << 4 << "Foo\n"; + QTest::newRow("at 4 Foo\\nBar\\n") << QStringLiteral("Foo\nBar\n") << 1 << (int) QAccessible::LineBoundary << 0 << 7 << 4 << 8 << "Bar\n"; + QTest::newRow("after 4 Foo\\nBar\\n") << QStringLiteral("Foo\nBar\n") << 2 << (int) QAccessible::LineBoundary << 0 << 7 << 8 << 8 << ""; + QTest::newRow("at 0 Foo\\n") << QStringLiteral("Foo\n") << 1 << (int) QAccessible::LineBoundary << 0 << 0 << 0 << 4 << "Foo\n"; +} + +void tst_QAccessibility::textInterfaceTest() +{ + QFETCH(QString, text); + QFETCH(int, textFunction); + QFETCH(int, boundaryType); + QFETCH(int, cursorPosition); + QFETCH(int, offset); + QFETCH(int, expectedStart); + QFETCH(int, expectedEnd); + QFETCH(QString, expectedText); + + QAccessible::installFactory(CustomTextWidgetIface::ifaceFactory); + CustomTextWidget *w = new CustomTextWidget(); + w->text = text; + w->cursorPosition = cursorPosition; + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(w); + QVERIFY(iface); + QCOMPARE(iface->text(QAccessible::Value), text); + QAccessibleTextInterface *textIface = iface->textInterface(); + QVERIFY(textIface); + + int start = -33; + int end = -33; + QString result; + switch (textFunction) { + case 0: + result = textIface->textBeforeOffset(offset, (QAccessible::TextBoundaryType) boundaryType, &start, &end); + break; + case 1: + result = textIface->textAtOffset(offset, (QAccessible::TextBoundaryType) boundaryType, &start, &end); + break; + case 2: + result = textIface->textAfterOffset(offset, (QAccessible::TextBoundaryType) boundaryType, &start, &end); + break; + } + + QCOMPARE(result, expectedText); + QCOMPARE(start, expectedStart); + QCOMPARE(end, expectedEnd); + + delete w; + QAccessible::removeFactory(CustomTextWidgetIface::ifaceFactory); + QTestAccessibility::clearEvents(); +} + void tst_QAccessibility::groupBoxTest() { { From 68206db907f2f973986e816589d2a349708e6acc Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Wed, 20 Aug 2014 14:32:29 +0200 Subject: [PATCH 50/89] Improve accelerator stripping in accessible widgets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we strip the & we should also report the hotkey. In addition only strip labels when they are buddys and try not to remove ampersands from all kinds of random text. This fixes https://bugs.kde.org/show_bug.cgi?id=338282 Change-Id: I401281cd9ff43b23a3923ad9909ca9c469b59506 Reviewed-by: Jan Arve Sæther --- src/widgets/accessible/qaccessiblemenu.cpp | 3 +-- src/widgets/accessible/qaccessiblewidgets.cpp | 3 +++ src/widgets/accessible/simplewidgets.cpp | 15 ++++++++++----- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/widgets/accessible/qaccessiblemenu.cpp b/src/widgets/accessible/qaccessiblemenu.cpp index f47980d786..82c3675508 100644 --- a/src/widgets/accessible/qaccessiblemenu.cpp +++ b/src/widgets/accessible/qaccessiblemenu.cpp @@ -294,8 +294,7 @@ QString QAccessibleMenuItem::text(QAccessible::Text t) const QString str; switch (t) { case QAccessible::Name: - str = m_action->text(); - str = qt_accStripAmp(str); + str = qt_accStripAmp(m_action->text()); break; case QAccessible::Accelerator: { #ifndef QT_NO_SHORTCUT diff --git a/src/widgets/accessible/qaccessiblewidgets.cpp b/src/widgets/accessible/qaccessiblewidgets.cpp index cc6310d591..b28f05cf8e 100644 --- a/src/widgets/accessible/qaccessiblewidgets.cpp +++ b/src/widgets/accessible/qaccessiblewidgets.cpp @@ -73,6 +73,7 @@ QT_BEGIN_NAMESPACE QString qt_accStripAmp(const QString &text); +QString qt_accHotKey(const QString &text); QList childWidgets(const QWidget *widget) { @@ -636,6 +637,8 @@ QString QAccessibleDockWidget::text(QAccessible::Text t) const { if (t == QAccessible::Name) { return qt_accStripAmp(dockWidget()->windowTitle()); + } else if (t == QAccessible::Accelerator) { + return qt_accHotKey(dockWidget()->windowTitle()); } return QString(); } diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp index 2064914683..d5933a6804 100644 --- a/src/widgets/accessible/simplewidgets.cpp +++ b/src/widgets/accessible/simplewidgets.cpp @@ -121,14 +121,14 @@ QString QAccessibleButton::text(QAccessible::Text t) const case QAccessible::Name: str = widget()->accessibleName(); if (str.isEmpty()) - str = button()->text(); + str = qt_accStripAmp(button()->text()); break; default: break; } if (str.isEmpty()) str = QAccessibleWidget::text(t); - return qt_accStripAmp(str); + return str; } QAccessible::State QAccessibleButton::state() const @@ -395,6 +395,8 @@ QString QAccessibleDisplay::text(QAccessible::Text t) const doc.setHtml(str); str = doc.toPlainText(); } + if (label->buddy()) + str = qt_accStripAmp(str); #ifndef QT_NO_LCDNUMBER } else if (qobject_cast(object())) { QLCDNumber *l = qobject_cast(object()); @@ -419,7 +421,7 @@ QString QAccessibleDisplay::text(QAccessible::Text t) const } if (str.isEmpty()) str = QAccessibleWidget::text(t); - return qt_accStripAmp(str); + return str; } /*! \reimp */ @@ -508,7 +510,10 @@ QString QAccessibleGroupBox::text(QAccessible::Text t) const txt = qt_accStripAmp(groupBox()->title()); break; case QAccessible::Description: - txt = qt_accStripAmp(groupBox()->toolTip()); + txt = groupBox()->toolTip(); + break; + case QAccessible::Accelerator: + txt = qt_accHotKey(groupBox()->title()); break; default: break; @@ -611,7 +616,7 @@ QString QAccessibleLineEdit::text(QAccessible::Text t) const } if (str.isEmpty()) str = QAccessibleWidget::text(t); - return qt_accStripAmp(str); + return str; } void QAccessibleLineEdit::setText(QAccessible::Text t, const QString &text) From 8f88cc2c0f56108c79399e15402d4e181eae0d3a Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Thu, 4 Sep 2014 15:33:33 +0300 Subject: [PATCH 51/89] ANGLE: Fix compilation with MinGW + D3D11 Provide workarounds for things GCC doesn't like, and define a number of macros not found in the MinGW headers. Change-Id: I254c208209c0071fae5efb6727f2b3cfd5542da6 Reviewed-by: Kai Koehne --- src/3rdparty/angle/src/libGLESv2/Context.cpp | 4 +- .../libGLESv2/renderer/d3d/d3d11/Buffer11.cpp | 4 + .../libGLESv2/renderer/d3d/d3d11/Query11.cpp | 8 + .../renderer/d3d/d3d11/RenderTarget11.h | 2 +- .../renderer/d3d/d3d11/Renderer11.cpp | 27 ++- .../libGLESv2/renderer/d3d/d3d11/Renderer11.h | 2 +- .../renderer/d3d/d3d11/renderer11_utils.cpp | 11 +- ...GLE-Fix-compilation-with-MinGW-D3D11.patch | 175 ++++++++++++++++++ 8 files changed, 227 insertions(+), 6 deletions(-) create mode 100644 src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp index 8201acda10..99df85b0d3 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp @@ -368,7 +368,7 @@ void Context::deleteFenceSync(GLsync fenceSync) // wait commands finish. However, since the name becomes invalid, we cannot query the fence, // and since our API is currently designed for being called from a single thread, we can delete // the fence immediately. - mResourceManager->deleteFenceSync(reinterpret_cast(fenceSync)); + mResourceManager->deleteFenceSync(uintptr_t(fenceSync)); } void Context::deleteVertexArray(GLuint vertexArray) @@ -474,7 +474,7 @@ Renderbuffer *Context::getRenderbuffer(GLuint handle) FenceSync *Context::getFenceSync(GLsync handle) const { - return mResourceManager->getFenceSync(reinterpret_cast(handle)); + return mResourceManager->getFenceSync(uintptr_t(handle)); } VertexArray *Context::getVertexArray(GLuint handle) const diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp index 352da9654a..1301124b2d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp @@ -12,6 +12,10 @@ #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#if defined(__MINGW32__) && !defined(D3D11_MAP_FLAG_DO_NOT_WAIT) +# define D3D11_MAP_FLAG_DO_NOT_WAIT 0x100000L +#endif + namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp index 17cf5cad47..e5e00325b2 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp @@ -12,6 +12,14 @@ #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" #include "libGLESv2/main.h" +#if defined(__MINGW32__) // Provide undefined struct +typedef struct D3D11_QUERY_DATA_SO_STATISTICS +{ + UINT64 NumPrimitivesWritten; + UINT64 PrimitivesStorageNeeded; +} D3D11_QUERY_DATA_SO_STATISTICS; +#endif + namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h index ba9f76e5de..82182957af 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h @@ -51,4 +51,4 @@ class RenderTarget11 : public RenderTarget } -#endif LIBGLESV2_RENDERER_RENDERTARGET11_H_ +#endif // LIBGLESV2_RENDERER_RENDERTARGET11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp index 651b065ca2..3ba0cc767b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp @@ -49,6 +49,31 @@ #define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1 #endif +#ifndef D3D11_PS_INPUT_REGISTER_COUNT +# define D3D11_PS_INPUT_REGISTER_COUNT 32 +#endif +#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT +# define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32 +#endif +#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT +# define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14 +#endif +#ifndef D3D11_SO_BUFFER_SLOT_COUNT +# define D3D11_SO_BUFFER_SLOT_COUNT 4 +#endif +#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT +# define D3D10_1_SO_BUFFER_SLOT_COUNT 4 +#endif +#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT +# define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096 +#endif +#ifndef D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP +# define D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP 32 +#endif +#ifndef D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP +# define D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP 32 +#endif + namespace rx { static const DXGI_FORMAT RenderTargetFormats[] = @@ -275,7 +300,7 @@ EGLint Renderer11::initialize() } // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log -#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) +#if !defined(__MINGW32__) && defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) ID3D11InfoQueue *infoQueue; result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h index a31f15ee64..b54f75d859 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h @@ -261,7 +261,7 @@ class Renderer11 : public Renderer }; MultisampleSupportInfo getMultisampleSupportInfo(DXGI_FORMAT format); - typedef std::unordered_map MultisampleSupportMap; + typedef std::unordered_map MultisampleSupportMap; MultisampleSupportMap mMultisampleSupportMap; unsigned int mMaxSupportedSamples; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp index 8e0c21bd83..d914a8201b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp @@ -36,6 +36,15 @@ #ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION # define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096 #endif +#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION +# define D3D11_REQ_TEXTURECUBE_DIMENSION 16384 +#endif +#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION +# define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION 2048 +#endif +#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION +# define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 2048 +#endif namespace rx { @@ -671,7 +680,7 @@ void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, flo HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) { -#if defined(_DEBUG) +#if !defined(__MINGW32__) && defined(_DEBUG) return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name); #else return S_OK; diff --git a/src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch b/src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch new file mode 100644 index 0000000000..3cf6c67d16 --- /dev/null +++ b/src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch @@ -0,0 +1,175 @@ +From ac4e9bb72ca22fd39bfc43f087108694db2ae8ac Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Thu, 4 Sep 2014 15:32:17 +0300 +Subject: [PATCH] ANGLE: Fix compilation with MinGW + D3D11 + +Provide workarounds for things GCC doesn't like, and define a number +of macros not found in the MinGW headers. + +Change-Id: I254c208209c0071fae5efb6727f2b3cfd5542da6 +--- + src/3rdparty/angle/src/libGLESv2/Context.cpp | 4 ++-- + .../src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp | 4 ++++ + .../src/libGLESv2/renderer/d3d/d3d11/Query11.cpp | 8 +++++++ + .../libGLESv2/renderer/d3d/d3d11/RenderTarget11.h | 2 +- + .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 27 +++++++++++++++++++++- + .../src/libGLESv2/renderer/d3d/d3d11/Renderer11.h | 2 +- + .../renderer/d3d/d3d11/renderer11_utils.cpp | 11 ++++++++- + 7 files changed, 52 insertions(+), 6 deletions(-) + +diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp +index 8201acd..99df85b 100644 +--- a/src/3rdparty/angle/src/libGLESv2/Context.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp +@@ -368,7 +368,7 @@ void Context::deleteFenceSync(GLsync fenceSync) + // wait commands finish. However, since the name becomes invalid, we cannot query the fence, + // and since our API is currently designed for being called from a single thread, we can delete + // the fence immediately. +- mResourceManager->deleteFenceSync(reinterpret_cast(fenceSync)); ++ mResourceManager->deleteFenceSync(uintptr_t(fenceSync)); + } + + void Context::deleteVertexArray(GLuint vertexArray) +@@ -474,7 +474,7 @@ Renderbuffer *Context::getRenderbuffer(GLuint handle) + + FenceSync *Context::getFenceSync(GLsync handle) const + { +- return mResourceManager->getFenceSync(reinterpret_cast(handle)); ++ return mResourceManager->getFenceSync(uintptr_t(handle)); + } + + VertexArray *Context::getVertexArray(GLuint handle) const +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp +index 352da96..1301124 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp +@@ -12,6 +12,10 @@ + #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" + #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" + ++#if defined(__MINGW32__) && !defined(D3D11_MAP_FLAG_DO_NOT_WAIT) ++# define D3D11_MAP_FLAG_DO_NOT_WAIT 0x100000L ++#endif ++ + namespace rx + { + +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp +index 17cf5ca..e5e0032 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp +@@ -12,6 +12,14 @@ + #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" + #include "libGLESv2/main.h" + ++#if defined(__MINGW32__) // Provide undefined struct ++typedef struct D3D11_QUERY_DATA_SO_STATISTICS ++{ ++ UINT64 NumPrimitivesWritten; ++ UINT64 PrimitivesStorageNeeded; ++} D3D11_QUERY_DATA_SO_STATISTICS; ++#endif ++ + namespace rx + { + +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h +index ba9f76e..8218295 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h +@@ -51,4 +51,4 @@ class RenderTarget11 : public RenderTarget + + } + +-#endif LIBGLESV2_RENDERER_RENDERTARGET11_H_ ++#endif // LIBGLESV2_RENDERER_RENDERTARGET11_H_ +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp +index 651b065..3ba0cc7 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp +@@ -49,6 +49,31 @@ + #define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1 + #endif + ++#ifndef D3D11_PS_INPUT_REGISTER_COUNT ++# define D3D11_PS_INPUT_REGISTER_COUNT 32 ++#endif ++#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT ++# define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32 ++#endif ++#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT ++# define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14 ++#endif ++#ifndef D3D11_SO_BUFFER_SLOT_COUNT ++# define D3D11_SO_BUFFER_SLOT_COUNT 4 ++#endif ++#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT ++# define D3D10_1_SO_BUFFER_SLOT_COUNT 4 ++#endif ++#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT ++# define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096 ++#endif ++#ifndef D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP ++# define D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP 32 ++#endif ++#ifndef D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP ++# define D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP 32 ++#endif ++ + namespace rx + { + static const DXGI_FORMAT RenderTargetFormats[] = +@@ -275,7 +300,7 @@ EGLint Renderer11::initialize() + } + + // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log +-#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) ++#if !defined(__MINGW32__) && defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) + ID3D11InfoQueue *infoQueue; + result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue); + +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h +index a31f15e..b54f75d 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h +@@ -261,7 +261,7 @@ class Renderer11 : public Renderer + }; + MultisampleSupportInfo getMultisampleSupportInfo(DXGI_FORMAT format); + +- typedef std::unordered_map MultisampleSupportMap; ++ typedef std::unordered_map MultisampleSupportMap; + MultisampleSupportMap mMultisampleSupportMap; + + unsigned int mMaxSupportedSamples; +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp +index 8e0c21b..d914a82 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp +@@ -36,6 +36,15 @@ + #ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION + # define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096 + #endif ++#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION ++# define D3D11_REQ_TEXTURECUBE_DIMENSION 16384 ++#endif ++#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION ++# define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION 2048 ++#endif ++#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION ++# define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 2048 ++#endif + + namespace rx + { +@@ -671,7 +680,7 @@ void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, flo + + HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) + { +-#if defined(_DEBUG) ++#if !defined(__MINGW32__) && defined(_DEBUG) + return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name); + #else + return S_OK; +-- +1.9.0.msysgit.0 + From 2f0fa59d5903d4c9596ed42dcbaa9da0f77c78da Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Thu, 4 Sep 2014 16:04:23 +0300 Subject: [PATCH 52/89] Add KMS hooks for EGLFS plugin Change-Id: Ic703334e52726cdd815cccf152d9d01aa63c803c Reviewed-by: Laszlo Agocs --- src/plugins/platforms/eglfs/eglfs.pri | 5 + .../platforms/eglfs/qeglfshooks_kms.cpp | 422 ++++++++++++++++++ 2 files changed, 427 insertions(+) create mode 100644 src/plugins/platforms/eglfs/qeglfshooks_kms.cpp diff --git a/src/plugins/platforms/eglfs/eglfs.pri b/src/plugins/platforms/eglfs/eglfs.pri index 6e3ba54b97..6f463ba7d9 100644 --- a/src/plugins/platforms/eglfs/eglfs.pri +++ b/src/plugins/platforms/eglfs/eglfs.pri @@ -8,6 +8,11 @@ DEFINES += MESA_EGL_NO_X11_HEADERS # EGLFS_PLATFORM_HOOKS_SOURCES += qeglfshooks_x11.cpp # LIBS += -lX11 -lX11-xcb -lxcb +# Uncomment these to enable the KMS hooks. +# EGLFS_PLATFORM_HOOKS_SOURCES += qeglfshooks_kms.cpp +# CONFIG += link_pkgconfig +# PKGCONFIG += libdrm gbm + SOURCES += $$PWD/qeglfsintegration.cpp \ $$PWD/qeglfswindow.cpp \ $$PWD/qeglfsscreen.cpp \ diff --git a/src/plugins/platforms/eglfs/qeglfshooks_kms.cpp b/src/plugins/platforms/eglfs/qeglfshooks_kms.cpp new file mode 100644 index 0000000000..9e5d624d87 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfshooks_kms.cpp @@ -0,0 +1,422 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the qmake spec 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 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 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qeglfshooks.h" +#include +#include +#include +#include + +#include +#include +#include + +QT_USE_NAMESPACE + +class QEglKmsHooks : public QEglFSHooks +{ +public: + QEglKmsHooks(); + + void platformInit() Q_DECL_OVERRIDE; + void platformDestroy() Q_DECL_OVERRIDE; + EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE; + QSizeF physicalScreenSize() const Q_DECL_OVERRIDE; + QSize screenSize() const Q_DECL_OVERRIDE; + int screenDepth() const Q_DECL_OVERRIDE; + QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const Q_DECL_OVERRIDE; + EGLNativeWindowType createNativeWindow(QPlatformWindow *platformWindow, + const QSize &size, + const QSurfaceFormat &format) Q_DECL_OVERRIDE; + void destroyNativeWindow(EGLNativeWindowType window) Q_DECL_OVERRIDE; + bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; + void waitForVSync() const Q_DECL_OVERRIDE; + + void waitForVSyncImpl(); + bool setup_kms(); + + struct FrameBuffer { + FrameBuffer() : fb(0) {} + uint32_t fb; + }; + FrameBuffer *framebufferForBufferObject(gbm_bo *bo); + +private: + // device bits + QByteArray m_device; + int m_dri_fd; + gbm_device *m_gbm_device; + + // KMS bits + drmModeConnector *m_drm_connector; + drmModeEncoder *m_drm_encoder; + drmModeModeInfo m_drm_mode; + quint32 m_drm_crtc; + + // Drawing bits + gbm_surface *m_gbm_surface; +}; + +static QEglKmsHooks kms_hooks; +QEglFSHooks *platformHooks = &kms_hooks; + +QEglKmsHooks::QEglKmsHooks() + : m_dri_fd(-1) + , m_gbm_device(Q_NULLPTR) + , m_drm_connector(Q_NULLPTR) + , m_drm_encoder(Q_NULLPTR) + , m_drm_crtc(0) + , m_gbm_surface(Q_NULLPTR) +{ + +} + +void QEglKmsHooks::platformInit() +{ + QDeviceDiscovery *d = QDeviceDiscovery::create(QDeviceDiscovery::Device_VideoMask); + QStringList devices = d->scanConnectedDevices(); + d->deleteLater(); + + if (devices.isEmpty()) + qFatal("Could not find DRM device!"); + + m_device = devices.first().toLocal8Bit(); + m_dri_fd = qt_safe_open(m_device.constData(), O_RDWR | O_CLOEXEC); + if (m_dri_fd == -1) { + qErrnoWarning("Could not open DRM device %s", m_device.constData()); + qFatal("DRM device required, aborting."); + } + + if (!setup_kms()) + qFatal("Could not set up KMS on device %s!", m_device.constData()); + + m_gbm_device = gbm_create_device(m_dri_fd); + if (!m_gbm_device) + qFatal("Could not initialize gbm on device %s!", m_device.constData()); +} + +void QEglKmsHooks::platformDestroy() +{ + gbm_device_destroy(m_gbm_device); + m_gbm_device = Q_NULLPTR; + + if (qt_safe_close(m_dri_fd) == -1) + qErrnoWarning("Could not close DRM device %s", m_device.constData()); + + m_dri_fd = -1; +} + +EGLNativeDisplayType QEglKmsHooks::platformDisplay() const +{ + return static_cast(m_gbm_device); +} + +QSizeF QEglKmsHooks::physicalScreenSize() const +{ + return QSizeF(m_drm_connector->mmWidth, + m_drm_connector->mmHeight); +} + +QSize QEglKmsHooks::screenSize() const +{ + return QSize(m_drm_mode.hdisplay, + m_drm_mode.vdisplay); +} + +int QEglKmsHooks::screenDepth() const +{ + return 32; +} + +QSurfaceFormat QEglKmsHooks::surfaceFormatFor(const QSurfaceFormat &inputFormat) const +{ + QSurfaceFormat format(inputFormat); + format.setRenderableType(QSurfaceFormat::OpenGLES); + format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); + format.setRedBufferSize(8); + format.setGreenBufferSize(8); + format.setBlueBufferSize(8); + return format; +} + +EGLNativeWindowType QEglKmsHooks::createNativeWindow(QPlatformWindow *platformWindow, + const QSize &size, + const QSurfaceFormat &format) +{ + Q_UNUSED(platformWindow); + Q_UNUSED(size); + Q_UNUSED(format); + + if (m_gbm_surface) { + qWarning("Only single window apps supported!"); + return 0; + } + + m_gbm_surface = gbm_surface_create(m_gbm_device, + screenSize().width(), + screenSize().height(), + GBM_FORMAT_XRGB8888, + GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); + if (!m_gbm_surface) + qFatal("Could not initialize GBM surface"); + + return reinterpret_cast(m_gbm_surface); +} + +void QEglKmsHooks::destroyNativeWindow(EGLNativeWindowType window) +{ + gbm_surface *surface = reinterpret_cast(window); + if (surface == m_gbm_surface) + m_gbm_surface = Q_NULLPTR; + gbm_surface_destroy(surface); +} + +bool QEglKmsHooks::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case QPlatformIntegration::ThreadedPixmaps: + case QPlatformIntegration::OpenGL: + case QPlatformIntegration::ThreadedOpenGL: + case QPlatformIntegration::BufferQueueingOpenGL: + return true; + default: + return false; + } +} + +static void gbm_bo_destroyed_callback(gbm_bo *bo, void *data) +{ + QEglKmsHooks::FrameBuffer *fb = static_cast(data); + + if (fb->fb) { + gbm_device *device = gbm_bo_get_device(bo); + drmModeRmFB(gbm_device_get_fd(device), fb->fb); + } + + delete fb; +} + +QEglKmsHooks::FrameBuffer *QEglKmsHooks::framebufferForBufferObject(gbm_bo *bo) +{ + { + FrameBuffer *fb = static_cast(gbm_bo_get_user_data(bo)); + if (fb) + return fb; + } + + uint32_t width = gbm_bo_get_width(bo); + uint32_t height = gbm_bo_get_height(bo); + uint32_t stride = gbm_bo_get_stride(bo); + uint32_t handle = gbm_bo_get_handle(bo).u32; + + QScopedPointer fb(new FrameBuffer); + + int ret = drmModeAddFB(m_dri_fd, width, height, 24, 32, + stride, handle, &fb->fb); + + if (ret) { + qWarning("Failed to create KMS FB!"); + return Q_NULLPTR; + } + + gbm_bo_set_user_data(bo, fb.data(), gbm_bo_destroyed_callback); + return fb.take(); +} + +static void page_flip_handler(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *user_data) +{ + Q_UNUSED(fd); + Q_UNUSED(sequence); + Q_UNUSED(tv_sec); + Q_UNUSED(tv_usec); + + // We are no longer flipping + *static_cast(user_data) = false; +} + +void QEglKmsHooks::waitForVSync() const +{ + const_cast(this)->waitForVSyncImpl(); +} + +void QEglKmsHooks::waitForVSyncImpl() +{ + if (!m_gbm_surface) { + qWarning("Cannot sync before platform init!"); + return; + } + + if (!gbm_surface_has_free_buffers(m_gbm_surface)) { + qWarning("Out of free GBM buffers!"); + return; + } + + gbm_bo *front_buffer = gbm_surface_lock_front_buffer(m_gbm_surface); + if (!front_buffer) { + qWarning("Could not lock GBM surface front buffer!"); + return; + } + + QEglKmsHooks::FrameBuffer *fb = framebufferForBufferObject(front_buffer); + + int ret = drmModeSetCrtc(m_dri_fd, + m_drm_crtc, + fb->fb, + 0, 0, + &m_drm_connector->connector_id, 1, + &m_drm_mode); + if (ret) { + qErrnoWarning("Could not set DRM mode!"); + return; + } + + bool flipping = true; + ret = drmModePageFlip(m_dri_fd, + m_drm_encoder->crtc_id, + fb->fb, + DRM_MODE_PAGE_FLIP_EVENT, + &flipping); + if (ret) { + qErrnoWarning("Could not queue DRM page flip!"); + return; + } + + drmEventContext drmEvent = { + DRM_EVENT_CONTEXT_VERSION, + Q_NULLPTR, // vblank handler + page_flip_handler // page flip handler + }; + + fd_set fds; + FD_ZERO(&fds); + FD_SET(m_dri_fd, &fds); + + time_t start, cur; + time(&start); + + while (flipping && (time(&cur) < start + 1)) { + timespec v; + memset(&v, 0, sizeof(v)); + v.tv_sec = start + 1 - cur; + + ret = qt_safe_select(m_dri_fd + 1, &fds, Q_NULLPTR, Q_NULLPTR, &v); + + if (ret == 0) { + // timeout + break; + } else if (ret == -1) { + qErrnoWarning("Error while selecting on DRM fd"); + break; + } else if (drmHandleEvent(m_dri_fd, &drmEvent)) { + qWarning("Could not handle DRM event!"); + } + } + + gbm_surface_release_buffer(m_gbm_surface, front_buffer); +} + +bool QEglKmsHooks::setup_kms() +{ + drmModeRes *resources; + drmModeConnector *connector; + drmModeEncoder *encoder; + quint32 crtc = 0; + int i; + + resources = drmModeGetResources(m_dri_fd); + if (!resources) { + qWarning("drmModeGetResources failed"); + return false; + } + + for (i = 0; i < resources->count_connectors; i++) { + connector = drmModeGetConnector(m_dri_fd, resources->connectors[i]); + if (connector == NULL) + continue; + + if (connector->connection == DRM_MODE_CONNECTED && + connector->count_modes > 0) { + break; + } + + drmModeFreeConnector(connector); + } + + if (i == resources->count_connectors) { + qWarning("No currently active connector found."); + return false; + } + + for (i = 0; i < resources->count_encoders; i++) { + encoder = drmModeGetEncoder(m_dri_fd, resources->encoders[i]); + + if (encoder == NULL) + continue; + + if (encoder->encoder_id == connector->encoder_id) + break; + + drmModeFreeEncoder(encoder); + } + + for (int j = 0; j < resources->count_crtcs; j++) { + if ((encoder->possible_crtcs & (1 << j))) { + crtc = resources->crtcs[j]; + break; + } + } + + if (crtc == 0) + qFatal("No suitable CRTC available"); + + m_drm_connector = connector; + m_drm_encoder = encoder; + m_drm_mode = connector->modes[0]; + m_drm_crtc = crtc; + + drmModeFreeResources(resources); + + return true; +} From 59385ff2ca16484d84116a91876987f503b64df2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 28 Jul 2014 14:46:18 +0200 Subject: [PATCH 53/89] iOS: Update QIOSScreen::nativeOrientation() for iOS8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For iOS8 and up [UIScreen bounds] changes based on the interface orientation, so we need to use [UIScreen nativeBounds] instead. Change-Id: I3fc12cfa417df26ca94c803e970bc2dc18a94378 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/ios/qiosscreen.mm | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index a814c042c7..f1184be1b4 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -373,8 +373,15 @@ qreal QIOSScreen::devicePixelRatio() const Qt::ScreenOrientation QIOSScreen::nativeOrientation() const { - // A UIScreen stays in the native orientation, regardless of rotation - return m_uiScreen.bounds.size.width >= m_uiScreen.bounds.size.height ? + CGRect nativeBounds = +#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0) + QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0 ? m_uiScreen.nativeBounds : +#endif + m_uiScreen.bounds; + + // All known iOS devices have a native orientation of portrait, but to + // be on the safe side we compare the width and height of the bounds. + return nativeBounds.size.width >= nativeBounds.size.height ? Qt::LandscapeOrientation : Qt::PortraitOrientation; } From e35841e37456f4c5bc494a1674bb3f014a4d93c1 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Tue, 2 Sep 2014 17:55:56 +0300 Subject: [PATCH 54/89] Fix endianness part of QSysInfo::buildAbi() string Both Q_LITTLE_ENDIAN and Q_BIG_ENDIAN macros are always defined on all architectures. So, byte order detection results in "little_endian" value for big endian systems. Test the system endianness in a right way, according to Q_BYTE_ORDER macro documentation. Change-Id: I5523f90567e78d679a3ff2902a8f5377ed39ceb1 Reviewed-by: Thiago Macieira --- src/corelib/global/archdetect.cpp | 6 +++--- tests/auto/corelib/global/qglobal/tst_qglobal.cpp | 13 +++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/corelib/global/archdetect.cpp b/src/corelib/global/archdetect.cpp index e35595e727..344c363031 100644 --- a/src/corelib/global/archdetect.cpp +++ b/src/corelib/global/archdetect.cpp @@ -83,10 +83,10 @@ # define ARCH_PROCESSOR "unknown" #endif -// endinanness -#if defined(Q_LITTLE_ENDIAN) +// endianness +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN # define ARCH_ENDIANNESS "little_endian" -#elif defined(Q_BIG_ENDIAN) +#elif Q_BYTE_ORDER == Q_BIG_ENDIAN # define ARCH_ENDIANNESS "big_endian" #endif diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp index 0389ae7976..076e3eee1c 100644 --- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp +++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp @@ -45,6 +45,8 @@ #include #include +#include +#include class tst_QGlobal: public QObject { @@ -65,6 +67,7 @@ private slots: void integerForSize(); void qprintable(); void qprintable_data(); + void buildAbiEndianness(); }; void tst_QGlobal::qIsNull() @@ -652,5 +655,15 @@ void tst_QGlobal::qprintable_data() } +void tst_QGlobal::buildAbiEndianness() +{ +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + QLatin1String endian("little_endian"); +#elif Q_BYTE_ORDER == Q_BIG_ENDIAN + QLatin1String endian("big_endian"); +#endif + QVERIFY(QSysInfo::buildAbi().contains(endian)); +} + QTEST_APPLESS_MAIN(tst_QGlobal) #include "tst_qglobal.moc" From 32a0e0cc616fa9c34ecb6f839b933588f7d4ff3e Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 2 Sep 2014 14:37:10 +0200 Subject: [PATCH 55/89] QCommonStyle: replace a QPolygon with a QPoint[] (I) No need to allocate dynamic memory for a fixed-size point array when QPainter has a (QPoint*,int) overload. Change-Id: I50c69103bba47e9f6de4f5616e8f40fee522ddc2 Reviewed-by: Friedemann Kleint --- src/widgets/styles/qcommonstyle.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index cc24c79c09..27431a4401 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -321,22 +321,24 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { QPen oldPen = p->pen(); if (header->sortIndicator & QStyleOptionHeader::SortUp) { - QPolygon pa(3); p->setPen(QPen(opt->palette.light(), 0)); p->drawLine(opt->rect.x() + opt->rect.width(), opt->rect.y(), opt->rect.x() + opt->rect.width() / 2, opt->rect.y() + opt->rect.height()); p->setPen(QPen(opt->palette.dark(), 0)); - pa.setPoint(0, opt->rect.x() + opt->rect.width() / 2, opt->rect.y() + opt->rect.height()); - pa.setPoint(1, opt->rect.x(), opt->rect.y()); - pa.setPoint(2, opt->rect.x() + opt->rect.width(), opt->rect.y()); - p->drawPolyline(pa); + const QPoint points[] = { + QPoint(opt->rect.x() + opt->rect.width() / 2, opt->rect.y() + opt->rect.height()), + QPoint(opt->rect.x(), opt->rect.y()), + QPoint(opt->rect.x() + opt->rect.width(), opt->rect.y()), + }; + p->drawPolyline(points, sizeof points / sizeof *points); } else if (header->sortIndicator & QStyleOptionHeader::SortDown) { - QPolygon pa(3); p->setPen(QPen(opt->palette.light(), 0)); - pa.setPoint(0, opt->rect.x(), opt->rect.y() + opt->rect.height()); - pa.setPoint(1, opt->rect.x() + opt->rect.width(), opt->rect.y() + opt->rect.height()); - pa.setPoint(2, opt->rect.x() + opt->rect.width() / 2, opt->rect.y()); - p->drawPolyline(pa); + const QPoint points[] = { + QPoint(opt->rect.x(), opt->rect.y() + opt->rect.height()), + QPoint(opt->rect.x() + opt->rect.width(), opt->rect.y() + opt->rect.height()), + QPoint(opt->rect.x() + opt->rect.width() / 2, opt->rect.y()), + }; + p->drawPolyline(points, sizeof points / sizeof *points); p->setPen(QPen(opt->palette.dark(), 0)); p->drawLine(opt->rect.x(), opt->rect.y() + opt->rect.height(), opt->rect.x() + opt->rect.width() / 2, opt->rect.y()); From e192643c2dbc9228b4057661bf58945195836206 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 2 Sep 2014 14:37:54 +0200 Subject: [PATCH 56/89] QCommonStyle: replace a QPolygon with a QPoint[] (II) No need to allocate dynamic memory for a fixed-size point array when QPainter has a (QPoint*,int) overload. Change-Id: Ifdf8224ddffe06ef7848562023e372e2c32b9ad6 Reviewed-by: Friedemann Kleint --- src/widgets/styles/qcommonstyle.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index 27431a4401..1657879852 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -521,11 +521,6 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q if (pe == PE_IndicatorSpinUp && fw) --sy; - QPolygon a; - if (pe == PE_IndicatorSpinDown) - a.setPoints(3, 0, 1, sw-1, 1, sh-2, sh-1); - else - a.setPoints(3, 0, sh-1, sw-1, sh-1, sh-2, 1); int bsx = 0; int bsy = 0; if (opt->state & State_Sunken) { @@ -537,7 +532,13 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q p->setPen(opt->palette.buttonText().color()); p->setBrush(opt->palette.buttonText()); p->setRenderHint(QPainter::Qt4CompatiblePainting); - p->drawPolygon(a); + if (pe == PE_IndicatorSpinDown) { + const QPoint points[] = { QPoint(0, 1), QPoint(sw-1, 1), QPoint(sh-2, sh-1) }; + p->drawPolygon(points, sizeof points / sizeof *points); + } else { + const QPoint points[] = { QPoint(0, sh-1), QPoint(sw-1, sh-1), QPoint(sh-2, 1) }; + p->drawPolygon(points, sizeof points / sizeof *points); + } p->restore(); break; } #endif // QT_NO_SPINBOX From 8478fc4e597101e183b94162a1e5b57de71820a1 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 2 Sep 2014 20:54:59 +0200 Subject: [PATCH 57/89] QCommonStyle: replace a QPolygon with a QPoint[] (III) No need to allocate dynamic memory for a fixed-size point array when QPainter has a (QPoint*,int) overload. Change-Id: Ie1eecd376a52b73572998ba253a032deaa0daaf9 Reviewed-by: Friedemann Kleint --- src/widgets/styles/qcommonstyle.cpp | 45 +++++++++++++++-------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index 1657879852..5c0362b830 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -1645,30 +1645,33 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, break; case CE_ToolBoxTabShape: if (const QStyleOptionToolBox *tb = qstyleoption_cast(opt)) { - int d = 20 + tb->rect.height() - 3; - QPolygon a(7); - if (tb->direction != Qt::RightToLeft) { - a.setPoint(0, -1, tb->rect.height() + 1); - a.setPoint(1, -1, 1); - a.setPoint(2, tb->rect.width() - d, 1); - a.setPoint(3, tb->rect.width() - 20, tb->rect.height() - 2); - a.setPoint(4, tb->rect.width() - 1, tb->rect.height() - 2); - a.setPoint(5, tb->rect.width() - 1, tb->rect.height() + 1); - a.setPoint(6, -1, tb->rect.height() + 1); - } else { - a.setPoint(0, tb->rect.width(), tb->rect.height() + 1); - a.setPoint(1, tb->rect.width(), 1); - a.setPoint(2, d - 1, 1); - a.setPoint(3, 20 - 1, tb->rect.height() - 2); - a.setPoint(4, 0, tb->rect.height() - 2); - a.setPoint(5, 0, tb->rect.height() + 1); - a.setPoint(6, tb->rect.width(), tb->rect.height() + 1); - } - p->setPen(tb->palette.mid().color().darker(150)); bool oldQt4CompatiblePainting = p->testRenderHint(QPainter::Qt4CompatiblePainting); p->setRenderHint(QPainter::Qt4CompatiblePainting); - p->drawPolygon(a); + int d = 20 + tb->rect.height() - 3; + if (tb->direction != Qt::RightToLeft) { + const QPoint points[] = { + QPoint(-1, tb->rect.height() + 1), + QPoint(-1, 1), + QPoint(tb->rect.width() - d, 1), + QPoint(tb->rect.width() - 20, tb->rect.height() - 2), + QPoint(tb->rect.width() - 1, tb->rect.height() - 2), + QPoint(tb->rect.width() - 1, tb->rect.height() + 1), + QPoint(-1, tb->rect.height() + 1), + }; + p->drawPolygon(points, sizeof points / sizeof *points); + } else { + const QPoint points[] = { + QPoint(tb->rect.width(), tb->rect.height() + 1), + QPoint(tb->rect.width(), 1), + QPoint(d - 1, 1), + QPoint(20 - 1, tb->rect.height() - 2), + QPoint(0, tb->rect.height() - 2), + QPoint(0, tb->rect.height() + 1), + QPoint(tb->rect.width(), tb->rect.height() + 1), + }; + p->drawPolygon(points, sizeof points / sizeof *points); + } p->setRenderHint(QPainter::Qt4CompatiblePainting, oldQt4CompatiblePainting); p->setPen(tb->palette.light().color()); if (tb->direction != Qt::RightToLeft) { From e4fb59c0afa17b3530102f3a32f2323bedd3faa6 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 3 Sep 2014 09:51:40 +0200 Subject: [PATCH 58/89] QCommonStyle: replace a QPolygon with a QPoint[] (IV) No need to allocate dynamic memory for a fixed-size point array when QPainter has a (QPoint*,int) overload. This one is a bit more complicated, as the QPolygon was returned from a helper function, so I wrapped the array in a minimal std::array-like StaticPolygonF. Together, these four QPolygon -> QPoint[] changes result in ca. 4.5K text size reduction for libQtWidgets. Change-Id: I082f199d5edb7a7782173fe3748220f373edac8a Reviewed-by: Giuseppe D'Angelo --- src/widgets/styles/qcommonstyle.cpp | 32 ++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index 5c0362b830..ce6d3d708f 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -3043,7 +3043,18 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt, #ifndef QT_NO_DIAL -static QPolygonF calcArrow(const QStyleOptionSlider *dial, qreal &a) +// in lieu of std::array, minimal API +template +struct StaticPolygonF +{ + QPointF data[N]; + + Q_DECL_CONSTEXPR int size() const { return N; } + Q_DECL_CONSTEXPR const QPointF *cbegin() const { return data; } + Q_DECL_CONSTEXPR const QPointF &operator[](int idx) const { return data[idx]; } +}; + +static StaticPolygonF<3> calcArrow(const QStyleOptionSlider *dial, qreal &a) { int width = dial->rect.width(); int height = dial->rect.height(); @@ -3067,13 +3078,14 @@ static QPolygonF calcArrow(const QStyleOptionSlider *dial, qreal &a) len = 5; int back = len / 2; - QPolygonF arrow(3); - arrow[0] = QPointF(0.5 + xc + len * qCos(a), - 0.5 + yc - len * qSin(a)); - arrow[1] = QPointF(0.5 + xc + back * qCos(a + Q_PI * 5 / 6), - 0.5 + yc - back * qSin(a + Q_PI * 5 / 6)); - arrow[2] = QPointF(0.5 + xc + back * qCos(a - Q_PI * 5 / 6), - 0.5 + yc - back * qSin(a - Q_PI * 5 / 6)); + StaticPolygonF<3> arrow = {{ + QPointF(0.5 + xc + len * qCos(a), + 0.5 + yc - len * qSin(a)), + QPointF(0.5 + xc + back * qCos(a + Q_PI * 5 / 6), + 0.5 + yc - back * qSin(a + Q_PI * 5 / 6)), + QPointF(0.5 + xc + back * qCos(a - Q_PI * 5 / 6), + 0.5 + yc - back * qSin(a - Q_PI * 5 / 6)), + }}; return arrow; } @@ -3575,12 +3587,12 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl p->drawArc(br, 240 * 16, 180 * 16); qreal a; - QPolygonF arrow(calcArrow(dial, a)); + const StaticPolygonF<3> arrow = calcArrow(dial, a); p->setPen(Qt::NoPen); p->setBrush(pal.button()); p->setRenderHint(QPainter::Qt4CompatiblePainting); - p->drawPolygon(arrow); + p->drawPolygon(arrow.cbegin(), arrow.size()); a = QStyleHelper::angle(QPointF(width / 2, height / 2), arrow[0]); p->setBrush(Qt::NoBrush); From 2eb61feb9bb27799de836099b778f7431eb25848 Mon Sep 17 00:00:00 2001 From: David Faure Date: Thu, 4 Sep 2014 19:05:11 +0200 Subject: [PATCH 59/89] Doc: QRect::isEmpty's documentation didn't match the code. The code says bool QRect::isValid() const { return x1 <= x2 && y1 <= y2; } so the documentation should say <= as well, rather than <. Change-Id: If52005879d2a758b5d1d64b552e6cd96341fae76 Reviewed-by: Marc Mutz --- src/corelib/tools/qrect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp index 04269e485b..57cc863696 100644 --- a/src/corelib/tools/qrect.cpp +++ b/src/corelib/tools/qrect.cpp @@ -284,7 +284,7 @@ QT_BEGIN_NAMESPACE Returns \c true if the rectangle is valid, otherwise returns \c false. - A valid rectangle has a left() < right() and top() < + A valid rectangle has a left() <= right() and top() <= bottom(). Note that non-trivial operations like intersections are not defined for invalid rectangles. A valid rectangle is not empty (i.e., isValid() == !isEmpty()). From b858e7af4fefeed051f5a7e0795872fd1b834220 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Tue, 2 Sep 2014 15:04:43 +0300 Subject: [PATCH 60/89] windows: Enable ANGLE D3D11 renderer by default Also, remove the -angle-d3d11 configure option, as it no longer is necessary to select the renderer at build time. The D3D11 renderer is the default renderer in upstream ANGLE, and has been shown to be a more reliable solution for developers running over remote desktop and inside virtual machines. It also provides more features to the OpenGL ES implementation. This configuration switch does not disable the D3D9 render; if the GPU does not support D3D11, D3D9 is used instead. [ChangeLog][QtGui][Windows] The ANGLE D3D11 renderer was enabled by default. Systems which cannot use the new renderer will automatically fall back to the D3D9 renderer at runtime. Task-number: QTBUG-41031 Change-Id: If894309c07d9309c236b63c36f37679f74375133 Reviewed-by: Friedemann Kleint Reviewed-by: Laszlo Agocs Reviewed-by: Tim Jenssen --- src/angle/angle.pro | 3 +-- src/angle/src/config.pri | 2 ++ tools/configure/configureapp.cpp | 15 +++------------ 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/angle/angle.pro b/src/angle/angle.pro index 78b53dfa14..c454fee8f9 100644 --- a/src/angle/angle.pro +++ b/src/angle/angle.pro @@ -6,6 +6,5 @@ SUBDIRS += src # 2) If we made a 'QtANGLE' module, the include directory would be flattened which won't work since # we need to support "#include " CONFIG += minimal_syncqt -QMAKE_SYNCQT_OPTIONS = -module QtANGLE/KHR -module QtANGLE/EGL -module QtANGLE/GLES2 -version none -angle_d3d11: QMAKE_SYNCQT_OPTIONS += -module QtANGLE/GLES3 +QMAKE_SYNCQT_OPTIONS = -module QtANGLE/KHR -module QtANGLE/EGL -module QtANGLE/GLES2 -module QtANGLE/GLES3 -version none load(qt_module_headers) diff --git a/src/angle/src/config.pri b/src/angle/src/config.pri index 88c65802de..07a18620da 100644 --- a/src/angle/src/config.pri +++ b/src/angle/src/config.pri @@ -39,6 +39,8 @@ DEFINES += _WINDOWS \ !winrt: DEFINES += ANGLE_ENABLE_D3D9 ANGLE_SKIP_DXGI_1_2_CHECK +CONFIG += angle_d3d11 # Remove to disable D3D11 renderer + angle_d3d11 { DEFINES += ANGLE_ENABLE_D3D11 ANGLE_DEFAULT_D3D11=1 !build_pass: message("Enabling D3D11 mode for ANGLE") diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 3471ed78ae..ddfb1d955b 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -566,9 +566,6 @@ void Configure::parseCmdLine() else if (configCmdLine.at(i) == "-angle") { dictionary[ "ANGLE" ] = "yes"; dictionary[ "ANGLE_FROM" ] = "commandline"; - } else if (configCmdLine.at(i) == "-angle-d3d11") { - dictionary[ "ANGLE" ] = "d3d11"; - dictionary[ "ANGLE_FROM" ] = "commandline"; } else if (configCmdLine.at(i) == "-no-angle") { dictionary[ "ANGLE" ] = "no"; dictionary[ "ANGLE_FROM" ] = "commandline"; @@ -1640,7 +1637,7 @@ void Configure::applySpecSpecifics() dictionary[ "ICU" ] = "qt"; dictionary[ "CE_CRT" ] = "yes"; dictionary[ "LARGE_FILE" ] = "no"; - dictionary[ "ANGLE" ] = "d3d11"; + dictionary[ "ANGLE" ] = "yes"; dictionary[ "DYNAMICGL" ] = "no"; } else if (dictionary.value("XQMAKESPEC").startsWith("wince")) { dictionary[ "STYLE_WINDOWSXP" ] = "no"; @@ -1931,7 +1928,6 @@ bool Configure::displayHelp() } desc("ANGLE", "yes", "-angle", "Use the ANGLE implementation of OpenGL ES 2.0."); - desc("ANGLE", "d3d11", "-angle-d3d11", "Use the Direct3D 11-based ANGLE implementation of OpenGL ES 2.0."); desc("ANGLE", "no", "-no-angle", "Do not use ANGLE.\nSee http://code.google.com/p/angleproject/\n"); // Qt\Windows only options go below here -------------------------------------------------------------------------------- desc("\nQt for Windows only:\n\n"); @@ -2124,7 +2120,7 @@ bool Configure::checkAngleAvailability(QString *errorMessage /* = 0 */) const } } - const QString directXLibrary = dictionary["ANGLE"] == "d3d11" ? QStringLiteral("d3d11.lib") : QStringLiteral("d3d9.lib"); + const QString directXLibrary = QStringLiteral("d3d11.lib"); // Ensures at least the June 2010 DXSDK is present if (!findFile(directXLibrary)) { if (errorMessage) *errorMessage = QString::fromLatin1("The library '%1' could not be found.").arg(directXLibrary); @@ -2577,8 +2573,7 @@ bool Configure::verifyConfiguration() } if (dictionary["DYNAMICGL"] == "yes") { - // Note that d3d11 is still allowed for ANGLE, hence the check for == "yes". - if (dictionary["OPENGL_ES_2"] == "yes" || dictionary["ANGLE"] == "yes") { + if (dictionary["OPENGL_ES_2"] == "yes" || dictionary["ANGLE"] != "no") { cout << "ERROR: Dynamic OpenGL cannot be used with -angle." << endl; dictionary[ "DONE" ] = "error"; } @@ -2660,15 +2655,11 @@ void Configure::generateOutputVars() // ANGLE -------------------------------------------------------- if (dictionary[ "ANGLE" ] != "no") { qtConfig += "angle"; - if (dictionary[ "ANGLE" ] == "d3d11") - qmakeConfig += "angle_d3d11"; } // Dynamic OpenGL loading --------------------------------------- if (dictionary[ "DYNAMICGL" ] != "no") { qtConfig += "dynamicgl"; - if (dictionary[ "ANGLE" ] == "d3d11") - qmakeConfig += "angle_d3d11"; } // Image formates ----------------------------------------------- From 176bd1edfadcb68b914a27de75502edeb1081253 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 29 Aug 2014 17:38:25 +0200 Subject: [PATCH 61/89] Windows styles: Add device pixel scaling for system metrics. Metrics obtained from the system must be scaled down when device pixel ration scaling is in effect. Factor out functions to return the device pixel values which might still be used for drawing. Task-number: QTBUG-38993 Task-number: QTBUG-38858 Change-Id: I6b90629e4979436bbb46f8c1fa1ee2253ada7ece Reviewed-by: Alessandro Portale --- src/widgets/styles/qwindowsstyle.cpp | 139 ++++++----- src/widgets/styles/qwindowsstyle_p_p.h | 10 + src/widgets/styles/qwindowsvistastyle.cpp | 102 ++++---- src/widgets/styles/qwindowsxpstyle.cpp | 269 ++++++++-------------- src/widgets/styles/qwindowsxpstyle_p_p.h | 68 +++++- 5 files changed, 291 insertions(+), 297 deletions(-) diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index cf0afd8031..44242177dc 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -118,6 +118,9 @@ enum QSliderDirection { SlUp, SlDown, SlLeft, SlRight }; /* \internal */ + +int QWindowsStylePrivate::m_appDevicePixelRatio = 0; + QWindowsStylePrivate::QWindowsStylePrivate() : alt_down(false), menuBarTimer(0) { @@ -130,6 +133,13 @@ QWindowsStylePrivate::QWindowsStylePrivate() #endif } +int QWindowsStylePrivate::appDevicePixelRatio() +{ + if (!QWindowsStylePrivate::m_appDevicePixelRatio) + QWindowsStylePrivate::m_appDevicePixelRatio = qRound(qApp->devicePixelRatio()); + return QWindowsStylePrivate::m_appDevicePixelRatio; +} + // Returns \c true if the toplevel parent of \a widget has seen the Alt-key bool QWindowsStylePrivate::hasSeenAlt(const QWidget *widget) const { @@ -295,19 +305,76 @@ void QWindowsStyle::polish(QPalette &pal) QCommonStyle::polish(pal); } +int QWindowsStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *, const QWidget *widget) +{ + switch (pm) { +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) + case QStyle::PM_DockWidgetFrameWidth: +# ifndef Q_OS_WINCE + return GetSystemMetrics(SM_CXFRAME); +# else + return GetSystemMetrics(SM_CXDLGFRAME); +# endif + break; + + case QStyle::PM_TitleBarHeight: + if (widget && (widget->windowType() == Qt::Tool)) { + // MS always use one less than they say +# ifndef Q_OS_WINCE + return GetSystemMetrics(SM_CYSMCAPTION) - 1; +# else + return GetSystemMetrics(SM_CYCAPTION) - 1; +# endif + } + return GetSystemMetrics(SM_CYCAPTION) - 1; + +# ifndef Q_OS_WINCE + case QStyle::PM_ScrollBarExtent: + { + NONCLIENTMETRICS ncm; + ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); + if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)) + return qMax(ncm.iScrollHeight, ncm.iScrollWidth); + } + break; +# endif // !Q_OS_WINCE + + case QStyle::PM_MdiSubWindowFrameWidth: +# ifndef Q_OS_WINCE + return GetSystemMetrics(SM_CYFRAME); +# else + return GetSystemMetrics(SM_CYDLGFRAME); +# endif +#else + Q_UNUSED(widget) +#endif // Q_OS_WIN + + default: + break; + } + return QWindowsStylePrivate::InvalidMetric; +} + /*! \reimp */ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QWidget *widget) const { - int ret; + int ret = QWindowsStylePrivate::pixelMetricFromSystemDp(pm, opt, widget); + if (ret != QWindowsStylePrivate::InvalidMetric) + return ret / QWindowsStylePrivate::devicePixelRatio(widget); + + ret = 0; switch (pm) { + case PM_ToolBarItemSpacing: + break; case PM_ButtonDefaultIndicator: case PM_ButtonShiftHorizontal: case PM_ButtonShiftVertical: case PM_MenuHMargin: case PM_MenuVMargin: + case PM_ToolBarItemMargin: ret = 1; break; case PM_DockWidgetSeparatorExtent: @@ -315,7 +382,6 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW break; #ifndef QT_NO_TABBAR case PM_TabBarTabShiftHorizontal: - ret = 0; break; case PM_TabBarTabShiftVertical: ret = 2; @@ -357,23 +423,14 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW if (space > 0) thick += (space * 2) / (n + 2); ret = thick; - } else { - ret = 0; } break; #endif // QT_NO_SLIDER #ifndef QT_NO_MENU case PM_MenuBarHMargin: - ret = 0; - break; - case PM_MenuBarVMargin: - ret = 0; - break; - case PM_MenuBarPanelWidth: - ret = 0; break; case PM_SmallIconSize: @@ -394,76 +451,16 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW case PM_DockWidgetTitleBarButtonMargin: ret = int(QStyleHelper::dpiScaled(4.)); break; -#if defined(Q_WS_WIN) - case PM_DockWidgetFrameWidth: -#if defined(Q_OS_WINCE) - ret = GetSystemMetrics(SM_CXDLGFRAME); -#else - ret = GetSystemMetrics(SM_CXFRAME); -#endif - break; -#else case PM_DockWidgetFrameWidth: ret = 4; break; -#endif // Q_WS_WIN break; #endif // QT_NO_MENU - - -#if defined(Q_OS_WIN) -#ifndef Q_OS_WINRT // There is no title bar in Windows Runtime applications - case PM_TitleBarHeight: - if (widget && (widget->windowType() == Qt::Tool)) { - // MS always use one less than they say -#if defined(Q_OS_WINCE) - ret = GetSystemMetrics(SM_CYCAPTION) - 1; -#else - ret = GetSystemMetrics(SM_CYSMCAPTION) - 1; -#endif - } else { - ret = GetSystemMetrics(SM_CYCAPTION) - 1; - } - - break; -#endif // !Q_OS_WINRT - - case PM_ScrollBarExtent: - { -#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) - NONCLIENTMETRICS ncm; - ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); - if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)) - ret = qMax(ncm.iScrollHeight, ncm.iScrollWidth); - else -#endif // !Q_OS_WINCE && !Q_OS_WINRT - ret = QCommonStyle::pixelMetric(pm, opt, widget); - } - break; -#endif // Q_OS_WIN - case PM_SplitterWidth: ret = qMax(4, QApplication::globalStrut().width()); break; -#if defined(Q_OS_WIN) -#ifndef Q_OS_WINRT // Mdi concept not available for WinRT applications - case PM_MdiSubWindowFrameWidth: -#if defined(Q_OS_WINCE) - ret = GetSystemMetrics(SM_CYDLGFRAME); -#else - ret = GetSystemMetrics(SM_CYFRAME); -#endif - break; -#endif // !Q_OS_WINRT -#endif // Q_OS_WIN - case PM_ToolBarItemMargin: - ret = 1; - break; - case PM_ToolBarItemSpacing: - ret = 0; - break; case PM_ToolBarHandleExtent: ret = int(QStyleHelper::dpiScaled(10.)); break; diff --git a/src/widgets/styles/qwindowsstyle_p_p.h b/src/widgets/styles/qwindowsstyle_p_p.h index 872b6f0e9e..8f70271357 100644 --- a/src/widgets/styles/qwindowsstyle_p_p.h +++ b/src/widgets/styles/qwindowsstyle_p_p.h @@ -68,7 +68,13 @@ class QWindowsStylePrivate : public QCommonStylePrivate { Q_DECLARE_PUBLIC(QWindowsStyle) public: + enum { InvalidMetric = -23576 }; + QWindowsStylePrivate(); + static int pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0); + static int devicePixelRatio(const QWidget *widget = 0) + { return widget ? widget->devicePixelRatio() : QWindowsStylePrivate::appDevicePixelRatio(); } + bool hasSeenAlt(const QWidget *widget) const; bool altDown() const { return alt_down; } bool alt_down; @@ -90,6 +96,10 @@ public: windowsRightBorder = 15, // right border on windows windowsCheckMarkWidth = 12 // checkmarks width on windows }; + +private: + static int appDevicePixelRatio(); + static int m_appDevicePixelRatio; }; QT_END_NAMESPACE diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index 672f5c78ac..69e21d0f56 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -409,9 +409,11 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt XPThemeData theme(0, painter, QWindowsXPStylePrivate::TreeViewTheme); static int decoration_size = 0; if (d->initTreeViewTheming() && theme.isValid() && !decoration_size) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, TVP_HOTGLYPH, GLPS_OPENED, 0, TS_TRUE, &size); - decoration_size = qMax(size.cx, size.cy); + XPThemeData themeSize = theme; + themeSize.partId = TVP_HOTGLYPH; + themeSize.stateId = GLPS_OPENED; + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + decoration_size = qMax(size.width(), size.height()); } int mid_h = option->rect.x() + option->rect.width() / 2; int mid_v = option->rect.y() + option->rect.height() / 2; @@ -990,10 +992,10 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ToolBarTheme, TP_DROPDOWNBUTTON); if (theme.isValid()) { - SIZE size; - if (QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) { - mbiw = size.cx; - mbih = size.cy; + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + if (!size.isEmpty()) { + mbiw = size.width(); + mbih = size.height(); } } QRect ir = subElementRect(SE_PushButtonContents, option, 0); @@ -1183,13 +1185,14 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption // windows always has a check column, regardless whether we have an icon or not int checkcol = 25; { - SIZE size; - MARGINS margins; XPThemeData theme(widget, 0, QWindowsXPStylePrivate::MenuTheme, MENU_POPUPCHECKBACKGROUND, MBI_HOT); - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); - QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins); - checkcol = qMax(menuitem->maxIconWidth, int(3 + size.cx + margins.cxLeftWidth + margins.cxRightWidth)); + XPThemeData themeSize = theme; + themeSize.partId = MENU_POPUPCHECK; + themeSize.stateId = 0; + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMargins margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + checkcol = qMax(menuitem->maxIconWidth, int(3 + size.width() + margins.left() + margins.right())); } QRect rect = option->rect; @@ -1241,20 +1244,20 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption QWindowsXPStylePrivate::MenuTheme, MENU_POPUPCHECKBACKGROUND, menuitem->icon.isNull() ? MBI_HOT : MBI_PUSHED, vCheckRect); - SIZE size; - MARGINS margins; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); - QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, - TMT_CONTENTMARGINS, NULL, &margins); - QRect checkRect(0, 0, size.cx + margins.cxLeftWidth + margins.cxRightWidth , - size.cy + margins.cyBottomHeight + margins.cyTopHeight); + XPThemeData themeSize = theme; + themeSize.partId = MENU_POPUPCHECK; + themeSize.stateId = 0; + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMargins margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + QRect checkRect(0, 0, size.width() + margins.left() + margins.right(), + size.height() + margins.bottom() + margins.top()); checkRect.moveCenter(vCheckRect.center()); theme.rect = checkRect; d->drawBackground(theme); if (menuitem->icon.isNull()) { - checkRect = QRect(0, 0, size.cx, size.cy); + checkRect = QRect(QPoint(0, 0), size); checkRect.moveCenter(theme.rect.center()); theme.rect = checkRect; @@ -1763,29 +1766,21 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle const int swidth = theme.rect.width(); const int sheight = theme.rect.height(); - MARGINS contentsMargin; - RECT rect = theme.toRECT(theme.rect); - QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin); + const QMargins contentsMargin = theme.margins(theme.rect, TMT_SIZINGMARGINS) + / QWindowsXPStylePrivate::devicePixelRatio(widget); - SIZE size; theme.partId = flags & State_Horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - int gw = size.cx, gh = size.cy; - + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); if (QSysInfo::WindowsVersion < QSysInfo::WV_WINDOWS8) { - QRect gripperBounds; - if (flags & State_Horizontal && ((swidth - contentsMargin.cxLeftWidth - contentsMargin.cxRightWidth) > gw)) { - gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); - gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); - gripperBounds.setWidth(gw); - gripperBounds.setHeight(gh); - } else if ((sheight - contentsMargin.cyTopHeight - contentsMargin.cyBottomHeight) > gh) { - gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); - gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); - gripperBounds.setWidth(gw); - gripperBounds.setHeight(gh); + QPoint gripperBoundsPos(0, 0); + if ((flags & State_Horizontal + && swidth - contentsMargin.left() - contentsMargin.right() > size.width()) + || sheight - contentsMargin.top() - contentsMargin.bottom() > size.height()) { + gripperBoundsPos = QPoint(theme.rect.left() + (swidth - size.width()) / 2, + theme.rect.top() + (sheight - size.height()) / 2); } + const QRect gripperBounds(gripperBoundsPos, size); // Draw gripper if there is enough space if (!gripperBounds.isEmpty() && flags & State_Enabled) { @@ -1883,15 +1878,16 @@ QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption sz = QWindowsXPStyle::sizeFromContents(type, option, size, widget); int minimumHeight; { - SIZE size; - MARGINS margins; XPThemeData theme(widget, 0, QWindowsXPStylePrivate::MenuTheme, MENU_POPUPCHECKBACKGROUND, MBI_HOT); - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); - QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins); - minimumHeight = qMax(size.cy + margins.cyBottomHeight+ margins.cyTopHeight, sz.height()); - sz.rwidth() += size.cx + margins.cxLeftWidth + margins.cxRightWidth; + XPThemeData themeSize = theme; + themeSize.partId = MENU_POPUPCHECK; + themeSize.stateId = 0; + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMargins margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + minimumHeight = qMax(size.height() + margins.bottom() + margins.top(), sz.height()); + sz.rwidth() += size.width() + margins.left() + margins.right(); } if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(option)) { @@ -1999,10 +1995,10 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption int arrowWidth = 13; int arrowHeight = 5; if (theme.isValid()) { - SIZE size; - if (QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) { - arrowWidth = size.cx; - arrowHeight = size.cy; + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + if (!size.isEmpty()) { + arrowWidth = size.width(); + arrowHeight = size.height(); } } if (option->state & State_Horizontal) { @@ -2195,7 +2191,8 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt const bool isToolTitle = false; const int height = tb->rect.height(); const int width = tb->rect.width(); - int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4; + int buttonWidth = GetSystemMetrics(SM_CXSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) + - 4; const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget); const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0; @@ -2531,14 +2528,13 @@ QIcon QWindowsVistaStyle::standardIcon(StandardPixmap standardIcon, QWindowsXPStylePrivate::ButtonTheme, BP_COMMANDLINKGLYPH, CMDLGS_NORMAL); if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); QIcon linkGlyph; - QPixmap pm = QPixmap(size.cx, size.cy); + QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); theme.painter = &p; - theme.rect = QRect(0, 0, size.cx, size.cy); + theme.rect = QRect(QPoint(0, 0), size); d->drawBackground(theme); linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal pm.fill(Qt::transparent); diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index 2e3586db42..424a1f7234 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -411,22 +411,21 @@ HWND QWindowsXPStylePrivate::winId(const QWidget *widget) height of the screen. This way the theme engine doesn't need to scale the body for every time we ask for it. (Speed optimization) */ -const QPixmap *QWindowsXPStylePrivate::tabBody(QWidget *) +const QPixmap *QWindowsXPStylePrivate::tabBody(QWidget *widget) { if (!tabbody) { - SIZE sz; XPThemeData theme(0, 0, QWindowsXPStylePrivate::TabTheme, TABP_BODY); - pGetThemePartSize(theme.handle(), qt_win_display_dc(), TABP_BODY, 0, 0, TS_TRUE, &sz); + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); - tabbody = new QPixmap(sz.cx, QApplication::desktop()->screenGeometry().height()); + tabbody = new QPixmap(size.width(), QApplication::desktop()->screenGeometry().height()); QPainter painter(tabbody); - theme.rect = QRect(0, 0, sz.cx, sz.cy); + theme.rect = QRect(QPoint(0, 0), size); drawBackground(theme); // We fill with the last line of the themedata, that // way we don't get a tiled pixmap inside big tabs - QPixmap temp(sz.cx, 1); - painter.drawPixmap(0, 0, temp, 0, sz.cy-1, -1, -1); - painter.drawTiledPixmap(0, sz.cy, sz.cx, tabbody->height()-sz.cy, temp); + QPixmap temp(size.width(), 1); + painter.drawPixmap(0, 0, temp, 0, size.height() - 1, -1, -1); + painter.drawTiledPixmap(0, size.height(), size.width(), tabbody->height() - size.height(), temp); } return tabbody; } @@ -2002,25 +2001,24 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op { themeNumber = QWindowsXPStylePrivate::StatusTheme; partId = SP_GRIPPER; - SIZE sz; XPThemeData theme(0, p, themeNumber, partId, 0); - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, partId, 0, 0, TS_TRUE, &sz); - --sz.cy; + QSize size = theme.size() / QWindowsStylePrivate::devicePixelRatio(widget); + size.rheight()--; if (const QStyleOptionSizeGrip *sg = qstyleoption_cast(option)) { switch (sg->corner) { case Qt::BottomRightCorner: - rect = QRect(rect.right() - sz.cx, rect.bottom() - sz.cy, sz.cx, sz.cy); + rect = QRect(QPoint(rect.right() - size.width(), rect.bottom() - size.height()), size); break; case Qt::BottomLeftCorner: - rect = QRect(rect.left() + 1, rect.bottom() - sz.cy, sz.cx, sz.cy); + rect = QRect(QPoint(rect.left() + 1, rect.bottom() - size.height()), size); hMirrored = true; break; case Qt::TopRightCorner: - rect = QRect(rect.right() - sz.cx, rect.top() + 1, sz.cx, sz.cy); + rect = QRect(QPoint(rect.right() - size.width(), rect.top() + 1), size); vMirrored = true; break; case Qt::TopLeftCorner: - rect = QRect(rect.left() + 1, rect.top() + 1, sz.cx, sz.cy); + rect = QRect(rect.topLeft() + QPoint(1, 1), size); hMirrored = vMirrored = true; } } @@ -2075,10 +2073,9 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op QWindowsXPStylePrivate::ToolBarTheme, TP_SPLITBUTTONDROPDOWN); if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - mbiw = size.cx; - mbih = size.cy; + const QSize size = theme.size() / QWindowsStylePrivate::devicePixelRatio(widget); + mbiw = size.width(); + mbih = size.height(); } QRect ir = btn->rect; @@ -2770,28 +2767,19 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo const int swidth = theme.rect.width(); const int sheight = theme.rect.height(); - MARGINS contentsMargin; - RECT rect = theme.toRECT(theme.rect); - QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin); + const QMargins contentsMargin = theme.margins(theme.rect, TMT_SIZINGMARGINS) + / QWindowsStylePrivate::devicePixelRatio(widget); - SIZE size; theme.partId = flags & State_Horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - int gw = size.cx, gh = size.cy; - - - QRect gripperBounds; - if (flags & State_Horizontal && ((swidth - contentsMargin.cxLeftWidth - contentsMargin.cxRightWidth) > gw)) { - gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); - gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); - gripperBounds.setWidth(gw); - gripperBounds.setHeight(gh); - } else if ((sheight - contentsMargin.cyTopHeight - contentsMargin.cyBottomHeight) > gh) { - gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); - gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); - gripperBounds.setWidth(gw); - gripperBounds.setHeight(gh); + const QSize size = theme.size() / QWindowsStylePrivate::devicePixelRatio(widget); + QPoint gripperBoundsPos(0, 0); + if ((flags & State_Horizontal + && swidth - contentsMargin.left() - contentsMargin.right() > size.width()) + || sheight - contentsMargin.top() - contentsMargin.bottom() > size.height()) { + gripperBoundsPos = QPoint(theme.rect.left() + (swidth - size.width()) / 2, + theme.rect.top() + (sheight - size.height()) /2); } + const QRect gripperBounds(gripperBoundsPos, size); // Draw gripper if there is enough space if (!gripperBounds.isEmpty()) { @@ -3113,9 +3101,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo } else { theme.partId = partId; theme.stateId = stateId; - SIZE sz; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), qt_win_display_dc(), theme.partId, theme.stateId, 0, TS_TRUE, &sz); - if (sz.cx == 0 || sz.cy == 0) { + if (theme.size().isEmpty()) { int iconSize = proxy()->pixelMetric(PM_SmallIconSize, tb, widget); QPixmap pm = proxy()->standardIcon(SP_TitleBarMenuButton, tb, widget).pixmap(iconSize, iconSize); p->save(); @@ -3330,23 +3316,63 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo } } +static inline Qt::Orientation progressBarOrientation(const QStyleOption *option = 0) +{ + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(option)) + return pb2->orientation; + return Qt::Horizontal; +} + +int QWindowsXPStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option, const QWidget *widget) +{ + switch (pm) { + case QStyle::PM_IndicatorWidth: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_CHECKBOX, CBS_UNCHECKEDNORMAL).width(); + case QStyle::PM_IndicatorHeight: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_CHECKBOX, CBS_UNCHECKEDNORMAL).height(); + case QStyle::PM_ExclusiveIndicatorWidth: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL).width(); + case QStyle::PM_ExclusiveIndicatorHeight: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL).height(); + case QStyle::PM_ProgressBarChunkWidth: + return progressBarOrientation(option) == Qt::Horizontal + ? XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ProgressTheme, PP_CHUNK).width() + : XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ProgressTheme, PP_CHUNKVERT).height(); + case QStyle::PM_SliderThickness: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::TrackBarTheme, TKP_THUMB).height(); + case QStyle::PM_TitleBarHeight: + return widget && (widget->windowType() == Qt::Tool) + ? GetSystemMetrics(SM_CYSMCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME) + : GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME); + case QStyle::PM_MdiSubWindowFrameWidth: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_FRAMELEFT, FS_ACTIVE).width(); + case QStyle::PM_DockWidgetFrameWidth: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLFRAMERIGHT, FS_ACTIVE).width(); + default: + break; + } + return QWindowsXPStylePrivate::InvalidMetric; +} + /*! \reimp */ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, const QWidget *widget) const { if (!QWindowsXPStylePrivate::useXP()) return QWindowsStyle::pixelMetric(pm, option, widget); - int res = 0; + int res = QWindowsXPStylePrivate::pixelMetricFromSystemDp(pm, option, widget); + if (res != QWindowsStylePrivate::InvalidMetric) + return res / QWindowsStylePrivate::devicePixelRatio(widget); + + res = 0; switch (pm) { case PM_MenuBarPanelWidth: + case PM_ButtonDefaultIndicator: res = 0; break; case PM_DefaultFrameWidth: - if (qobject_cast(widget)) - res = 2; - else - res = 1; + res = qobject_cast(widget) ? 2 : 1; break; case PM_MenuPanelWidth: case PM_SpinBoxFrameWidth: @@ -3364,6 +3390,8 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con switch (tab->shape) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: res = 1; break; case QTabBar::RoundedSouth: @@ -3374,10 +3402,6 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con case QTabBar::TriangularEast: res = 3; break; - case QTabBar::RoundedWest: - case QTabBar::TriangularWest: - res = 1; - break; } } break; @@ -3386,77 +3410,6 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con res = qMax(int(QStyleHelper::dpiScaled(5.)), QApplication::globalStrut().width()); break; - case PM_IndicatorWidth: - case PM_IndicatorHeight: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_CHECKBOX, CBS_UNCHECKEDNORMAL); - if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = (pm == PM_IndicatorWidth) ? size.cx : size.cy; - } - } - break; - - case PM_ExclusiveIndicatorWidth: - case PM_ExclusiveIndicatorHeight: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL); - if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = (pm == PM_ExclusiveIndicatorWidth) ? size.cx : size.cy; - } - } - break; - - case PM_ProgressBarChunkWidth: - { - Qt::Orientation orient = Qt::Horizontal; - if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(option)) - orient = pb2->orientation; - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ProgressTheme, - (orient == Qt::Horizontal) ? PP_CHUNK : PP_CHUNKVERT); - if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = (orient == Qt::Horizontal) ? size.cx : size.cy; - } - } - break; - - case PM_SliderThickness: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::TrackBarTheme, - TKP_THUMB); - if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = size.cy; - } - } - break; - - case PM_TitleBarHeight: - { - if (widget && (widget->windowType() == Qt::Tool)) - res = GetSystemMetrics(SM_CYSMCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME); - else - res = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME); - } - break; - - case PM_MdiSubWindowFrameWidth: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_FRAMELEFT, FS_ACTIVE); - if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, WP_FRAMELEFT, FS_ACTIVE, 0, TS_TRUE, &size); - res = size.cx-1; - } - } - break; - case PM_MdiSubWindowMinimizedWidth: res = 160; break; @@ -3467,33 +3420,14 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con break; #endif // QT_NO_TOOLBAR - case PM_DockWidgetFrameWidth: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLFRAMERIGHT, FS_ACTIVE); - if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = size.cx; - } - } - break; case PM_DockWidgetSeparatorExtent: - res = int(QStyleHelper::dpiScaled(4.)); - break; case PM_DockWidgetTitleMargin: res = int(QStyleHelper::dpiScaled(4.)); break; case PM_ButtonShiftHorizontal: case PM_ButtonShiftVertical: - if (qstyleoption_cast(option)) - res = 1; - else - res = 0; - break; - - case PM_ButtonDefaultIndicator: - res = 0; + res = qstyleoption_cast(option) ? 1 : 0; break; default: @@ -3573,8 +3507,11 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl const bool isToolTitle = false; const int height = tb->rect.height(); const int width = tb->rect.width(); - int buttonHeight = GetSystemMetrics(SM_CYSIZE) - 4; - int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4; + const int buttonMargin = 4; + int buttonHeight = GetSystemMetrics(SM_CYSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) + - buttonMargin; + int buttonWidth = GetSystemMetrics(SM_CXSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) + - buttonMargin; const int delta = buttonWidth + 2; int controlTop = option->rect.bottom() - buttonHeight - 2; const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget); @@ -3766,20 +3703,12 @@ QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt case CT_LineEdit: case CT_ComboBox: { - XPThemeData buttontheme(widget, 0, QWindowsXPStylePrivate::ButtonTheme); - HTHEME theme = buttontheme.handle(); - MARGINS borderSize; - if (theme) { - int result = QWindowsXPStylePrivate::pGetThemeMargins(theme, - NULL, - BP_PUSHBUTTON, - PBS_NORMAL, - TMT_CONTENTMARGINS, - NULL, - &borderSize); - if (result == S_OK) { - sz += QSize(borderSize.cxLeftWidth + borderSize.cxRightWidth - 2, - borderSize.cyBottomHeight + borderSize.cyTopHeight - 2); + XPThemeData buttontheme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_PUSHBUTTON, PBS_NORMAL); + if (buttontheme.isValid()) { + const QMargins borderSize = buttontheme.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + if (!borderSize.isNull()) { + sz.rwidth() += borderSize.left() + borderSize.right() - 2; + sz.rheight() += borderSize.bottom() + borderSize.top() - 2; } const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin) + 1); sz += QSize(qMax(pixelMetric(QStyle::PM_ScrollBarExtent, option, widget) @@ -3949,9 +3878,8 @@ QPixmap QWindowsXPStyle::standardPixmap(StandardPixmap standardPixmap, const QSt if (widget && widget->isWindow()) { XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL); if (theme.isValid()) { - SIZE sz; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &sz); - return QIcon(QWindowsStyle::standardPixmap(standardPixmap, option, widget)).pixmap(QSize(sz.cx, sz.cy)); + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + return QIcon(QWindowsStyle::standardPixmap(standardPixmap, option, widget)).pixmap(size); } } } @@ -3984,13 +3912,12 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, WP_MAXBUTTON, MAXBS_NORMAL); if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(themeSize.handle(), 0, themeSize.partId, themeSize.stateId, 0, TS_TRUE, &size); - QPixmap pm = QPixmap(size.cx, size.cy); + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); theme.painter = &p; - theme.rect = QRect(0, 0, size.cx, size.cy); + theme.rect = QRect(QPoint(0, 0), size); d->drawBackground(theme); d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal pm.fill(Qt::transparent); @@ -4019,14 +3946,13 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL); if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - QPixmap pm = QPixmap(size.cx, size.cy); + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); theme.painter = &p; theme.partId = WP_CLOSEBUTTON; // #### - theme.rect = QRect(0, 0, size.cx, size.cy); + theme.rect = QRect(QPoint(0, 0), size); d->drawBackground(theme); d->dockClose.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal pm.fill(Qt::transparent); @@ -4056,13 +3982,12 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, WP_RESTOREBUTTON, RBS_NORMAL); if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(themeSize.handle(), 0, themeSize.partId, themeSize.stateId, 0, TS_TRUE, &size); - QPixmap pm = QPixmap(size.cx, size.cy); + const QSize size = themeSize.size() / QWindowsStylePrivate::devicePixelRatio(widget); + QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); theme.painter = &p; - theme.rect = QRect(0, 0, size.cx, size.cy); + theme.rect = QRect(QPoint(0, 0), size); d->drawBackground(theme); d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal pm.fill(Qt::transparent); diff --git a/src/widgets/styles/qwindowsxpstyle_p_p.h b/src/widgets/styles/qwindowsxpstyle_p_p.h index 190055b24b..0ead58393f 100644 --- a/src/widgets/styles/qwindowsxpstyle_p_p.h +++ b/src/widgets/styles/qwindowsxpstyle_p_p.h @@ -219,9 +219,19 @@ public: HRGN mask(QWidget *widget); HTHEME handle(); - RECT toRECT(const QRect &qr); + static RECT toRECT(const QRect &qr); bool isValid(); + QSize size(); + QMargins margins(const QRect &rect, int propId = TMT_CONTENTMARGINS); + QMargins margins(int propId = TMT_CONTENTMARGINS); + + static QSize themeSize(const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, int part = 0, int state = 0); + static QMargins themeMargins(const QRect &rect, const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, + int part = 0, int state = 0, int propId = TMT_CONTENTMARGINS); + static QMargins themeMargins(const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, + int part = 0, int state = 0, int propId = TMT_CONTENTMARGINS); + const QWidget *widget; QPainter *painter; @@ -374,6 +384,8 @@ public: ~QWindowsXPStylePrivate() { cleanup(); } + static int pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0); + static HWND winId(const QWidget *widget); void init(bool force = false); @@ -432,6 +444,60 @@ private: static HTHEME m_themes[NThemes]; }; +inline QSize XPThemeData::size() +{ + QSize result(0, 0); + if (isValid()) { + SIZE size; + if (SUCCEEDED(QWindowsXPStylePrivate::pGetThemePartSize(handle(), 0, partId, stateId, 0, TS_TRUE, &size))) + result = QSize(size.cx, size.cy); + } + return result; +} + +inline QMargins XPThemeData::margins(const QRect &qRect, int propId) +{ + QMargins result(0, 0, 0 ,0); + if (isValid()) { + MARGINS margins; + RECT rect = XPThemeData::toRECT(qRect); + if (SUCCEEDED(QWindowsXPStylePrivate::pGetThemeMargins(handle(), 0, partId, stateId, propId, &rect, &margins))) + result = QMargins(margins.cxLeftWidth, margins.cyTopHeight, margins.cxRightWidth, margins.cyBottomHeight); + } + return result; +} + +inline QMargins XPThemeData::margins(int propId) +{ + QMargins result(0, 0, 0 ,0); + if (isValid()) { + MARGINS margins; + if (SUCCEEDED(QWindowsXPStylePrivate::pGetThemeMargins(handle(), 0, partId, stateId, propId, NULL, &margins))) + result = QMargins(margins.cxLeftWidth, margins.cyTopHeight, margins.cxRightWidth, margins.cyBottomHeight); + } + return result; +} + +inline QSize XPThemeData::themeSize(const QWidget *w, QPainter *p, int themeIn, int part, int state) +{ + XPThemeData theme(w, p, themeIn, part, state); + return theme.size(); +} + +inline QMargins XPThemeData::themeMargins(const QRect &rect, const QWidget *w, QPainter *p, int themeIn, + int part, int state, int propId) +{ + XPThemeData theme(w, p, themeIn, part, state); + return theme.margins(rect, propId); +} + +inline QMargins XPThemeData::themeMargins(const QWidget *w, QPainter *p, int themeIn, + int part, int state, int propId) +{ + XPThemeData theme(w, p, themeIn, part, state); + return theme.margins(propId); +} + #endif // QT_NO_STYLE_WINDOWS QT_END_NAMESPACE From 585cef5f901c5860d8f6dce3cd49dcddb7a8481a Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 29 Aug 2014 17:41:50 +0200 Subject: [PATCH 62/89] Windows styles: Scale hardcoded-values according to DPI. Factor out functions to return the fixed values and scale those. Task-number: QTBUG-38993 Task-number: QTBUG-38858 Change-Id: I59c70a206eae76bf08bc2aeb5cda5a740cd3d6dc Reviewed-by: Alessandro Portale --- src/widgets/styles/qwindowsstyle.cpp | 110 ++++++++++---------- src/widgets/styles/qwindowsstyle_p_p.h | 1 + src/widgets/styles/qwindowsvistastyle.cpp | 40 ++++--- src/widgets/styles/qwindowsvistastyle_p_p.h | 1 + src/widgets/styles/qwindowsxpstyle.cpp | 2 +- src/widgets/styles/qwindowsxpstyle_p_p.h | 1 + 6 files changed, 84 insertions(+), 71 deletions(-) diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index 44242177dc..2f04a20cd0 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -355,6 +355,57 @@ int QWindowsStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const return QWindowsStylePrivate::InvalidMetric; } +int QWindowsStylePrivate::fixedPixelMetric(QStyle::PixelMetric pm) +{ + switch (pm) { + case QStyle::PM_ToolBarItemSpacing: + return 0; + case QStyle::PM_ButtonDefaultIndicator: + case QStyle::PM_ButtonShiftHorizontal: + case QStyle::PM_ButtonShiftVertical: + case QStyle::PM_MenuHMargin: + case QStyle::PM_MenuVMargin: + case QStyle::PM_ToolBarItemMargin: + return 1; + break; + case QStyle::PM_DockWidgetSeparatorExtent: + return 4; +#ifndef QT_NO_TABBAR + case QStyle::PM_TabBarTabShiftHorizontal: + return 0; + case QStyle::PM_TabBarTabShiftVertical: + return 2; +#endif + +#ifndef QT_NO_SLIDER + case QStyle::PM_SliderLength: + return 11; +#endif // QT_NO_SLIDER + +#ifndef QT_NO_MENU + case QStyle::PM_MenuBarHMargin: + case QStyle::PM_MenuBarVMargin: + case QStyle::PM_MenuBarPanelWidth: + return 0; + case QStyle::PM_SmallIconSize: + return 16; + case QStyle::PM_LargeIconSize: + return 32; + case QStyle::PM_DockWidgetTitleMargin: + return 2; + case QStyle::PM_DockWidgetTitleBarButtonMargin: + case QStyle::PM_DockWidgetFrameWidth: + return 4; + +#endif // QT_NO_MENU + case QStyle::PM_ToolBarHandleExtent: + return 10; + default: + break; + } + return QWindowsStylePrivate::InvalidMetric; +} + /*! \reimp */ @@ -364,29 +415,13 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW if (ret != QWindowsStylePrivate::InvalidMetric) return ret / QWindowsStylePrivate::devicePixelRatio(widget); + ret = QWindowsStylePrivate::fixedPixelMetric(pm); + if (ret != QWindowsStylePrivate::InvalidMetric) + return int(QStyleHelper::dpiScaled(ret)); + ret = 0; switch (pm) { - case PM_ToolBarItemSpacing: - break; - case PM_ButtonDefaultIndicator: - case PM_ButtonShiftHorizontal: - case PM_ButtonShiftVertical: - case PM_MenuHMargin: - case PM_MenuVMargin: - case PM_ToolBarItemMargin: - ret = 1; - break; - case PM_DockWidgetSeparatorExtent: - ret = int(QStyleHelper::dpiScaled(4.)); - break; -#ifndef QT_NO_TABBAR - case PM_TabBarTabShiftHorizontal: - break; - case PM_TabBarTabShiftVertical: - ret = 2; - break; -#endif case PM_MaximumDragDistance: ret = QCommonStyle::pixelMetric(PM_MaximumDragDistance); if (ret == -1) @@ -394,10 +429,6 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW break; #ifndef QT_NO_SLIDER - case PM_SliderLength: - ret = int(QStyleHelper::dpiScaled(11.)); - break; - // Returns the number of pixels to use for the business part of the // slider (i.e., the non-tickmark portion). The remaining space is shared // equally between the tickmark regions. @@ -427,43 +458,14 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW break; #endif // QT_NO_SLIDER -#ifndef QT_NO_MENU - case PM_MenuBarHMargin: - case PM_MenuBarVMargin: - case PM_MenuBarPanelWidth: - break; - - case PM_SmallIconSize: - ret = int(QStyleHelper::dpiScaled(16.)); - break; - - case PM_LargeIconSize: - ret = int(QStyleHelper::dpiScaled(32.)); - break; - case PM_IconViewIconSize: ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget); break; - case PM_DockWidgetTitleMargin: - ret = int(QStyleHelper::dpiScaled(2.)); - break; - case PM_DockWidgetTitleBarButtonMargin: - ret = int(QStyleHelper::dpiScaled(4.)); - break; - case PM_DockWidgetFrameWidth: - ret = 4; - break; - break; - -#endif // QT_NO_MENU case PM_SplitterWidth: - ret = qMax(4, QApplication::globalStrut().width()); + ret = qMax(int(QStyleHelper::dpiScaled(4)), QApplication::globalStrut().width()); break; - case PM_ToolBarHandleExtent: - ret = int(QStyleHelper::dpiScaled(10.)); - break; default: ret = QCommonStyle::pixelMetric(pm, opt, widget); break; diff --git a/src/widgets/styles/qwindowsstyle_p_p.h b/src/widgets/styles/qwindowsstyle_p_p.h index 8f70271357..93994abf6d 100644 --- a/src/widgets/styles/qwindowsstyle_p_p.h +++ b/src/widgets/styles/qwindowsstyle_p_p.h @@ -72,6 +72,7 @@ public: QWindowsStylePrivate(); static int pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0); + static int fixedPixelMetric(QStyle::PixelMetric pm); static int devicePixelRatio(const QWidget *widget = 0) { return widget ? widget->devicePixelRatio() : QWindowsStylePrivate::appDevicePixelRatio(); } diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index 69e21d0f56..e5acd22f16 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -2192,7 +2192,7 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt const int height = tb->rect.height(); const int width = tb->rect.width(); int buttonWidth = GetSystemMetrics(SM_CXSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) - - 4; + - int(QStyleHelper::dpiScaled(4)); const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget); const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0; @@ -2265,28 +2265,36 @@ QStyle::SubControl QWindowsVistaStyle::hitTestComplexControl(ComplexControl cont return QWindowsXPStyle::hitTestComplexControl(control, option, pos, widget); } +int QWindowsVistaStylePrivate::fixedPixelMetric(QStyle::PixelMetric pm) +{ + switch (pm) { + case QStyle::PM_DockWidgetTitleBarButtonMargin: + return 5; + case QStyle::PM_ScrollBarSliderMin: + return 18; + case QStyle::PM_MenuHMargin: + case QStyle::PM_MenuVMargin: + return 0; + case QStyle::PM_MenuPanelWidth: + return 3; + default: + break; + } + return QWindowsVistaStylePrivate::InvalidMetric; +} + /*! \internal */ int QWindowsVistaStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const { - if (!QWindowsVistaStylePrivate::useVista()) { + if (!QWindowsVistaStylePrivate::useVista()) return QWindowsStyle::pixelMetric(metric, option, widget); - } - switch (metric) { - case PM_DockWidgetTitleBarButtonMargin: - return int(QStyleHelper::dpiScaled(5.)); - case PM_ScrollBarSliderMin: - return int(QStyleHelper::dpiScaled(18.)); - case PM_MenuHMargin: - case PM_MenuVMargin: - return 0; - case PM_MenuPanelWidth: - return 3; - default: - break; - } + int ret = QWindowsStylePrivate::fixedPixelMetric(metric); + if (ret != QWindowsStylePrivate::InvalidMetric) + return int(QStyleHelper::dpiScaled(ret)); + return QWindowsXPStyle::pixelMetric(metric, option, widget); } diff --git a/src/widgets/styles/qwindowsvistastyle_p_p.h b/src/widgets/styles/qwindowsvistastyle_p_p.h index a7f219db8d..9f54ec8f21 100644 --- a/src/widgets/styles/qwindowsvistastyle_p_p.h +++ b/src/widgets/styles/qwindowsvistastyle_p_p.h @@ -171,6 +171,7 @@ class QWindowsVistaStylePrivate : public QWindowsXPStylePrivate public: QWindowsVistaStylePrivate(); ~QWindowsVistaStylePrivate(); + static int fixedPixelMetric(QStyle::PixelMetric pm); static inline bool useVista(); bool transitionsEnabled() const; diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index 424a1f7234..08ebe1c5ad 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -3507,7 +3507,7 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl const bool isToolTitle = false; const int height = tb->rect.height(); const int width = tb->rect.width(); - const int buttonMargin = 4; + const int buttonMargin = int(QStyleHelper::dpiScaled(4)); int buttonHeight = GetSystemMetrics(SM_CYSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) - buttonMargin; int buttonWidth = GetSystemMetrics(SM_CXSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) diff --git a/src/widgets/styles/qwindowsxpstyle_p_p.h b/src/widgets/styles/qwindowsxpstyle_p_p.h index 0ead58393f..6e1cfe6db5 100644 --- a/src/widgets/styles/qwindowsxpstyle_p_p.h +++ b/src/widgets/styles/qwindowsxpstyle_p_p.h @@ -385,6 +385,7 @@ public: { cleanup(); } static int pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0); + static int fixedPixelMetric(QStyle::PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0); static HWND winId(const QWidget *widget); From 7b1dad80212b886424d43c8f94fb92962510fe7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeremy=20Lain=C3=A9?= Date: Thu, 4 Sep 2014 20:39:14 +0200 Subject: [PATCH 63/89] ssl: enable non-OpenSSL backends to compile QSslSocket tests Some of the QSslSocket tests use OpenSSL-specific symbols. This change fixes this issue. Change-Id: Ib67efa42a15facaf0ad34fc0466341a37d945d1e Reviewed-by: Andrew Knight --- tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index 33cee37b92..c2f004f756 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -138,7 +138,9 @@ private slots: void peerCertificate(); void peerCertificateChain(); void privateKey(); +#ifndef QT_NO_OPENSSL void privateKeyOpaque(); +#endif void protocol(); void protocolServerSide_data(); void protocolServerSide(); @@ -186,7 +188,9 @@ private slots: void writeBigChunk(); void blacklistedCertificates(); void versionAccessors(); +#ifndef QT_NO_OPENSSL void sslOptions(); +#endif void encryptWithoutConnecting(); void resume_data(); void resume(); @@ -810,6 +814,7 @@ void tst_QSslSocket::privateKey() { } +#ifndef QT_NO_OPENSSL void tst_QSslSocket::privateKeyOpaque() { if (!QSslSocket::supportsSsl()) @@ -839,6 +844,7 @@ void tst_QSslSocket::privateKeyOpaque() if (setProxy && !socket->waitForEncrypted(10000)) QSKIP("Skipping flaky test - See QTBUG-29941"); } +#endif void tst_QSslSocket::protocol() { @@ -2280,6 +2286,7 @@ void tst_QSslSocket::versionAccessors() qDebug() << QString::number(QSslSocket::sslLibraryVersionNumber(), 16); } +#ifndef QT_NO_OPENSSL void tst_QSslSocket::sslOptions() { if (!QSslSocket::supportsSsl()) @@ -2331,6 +2338,7 @@ void tst_QSslSocket::sslOptions() #endif #endif } +#endif void tst_QSslSocket::encryptWithoutConnecting() { From 863f598b650417824a8d531badc7a9d074af64be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeremy=20Lain=C3=A9?= Date: Fri, 5 Sep 2014 11:14:14 +0200 Subject: [PATCH 64/89] ssl: make peerVerifyError test agnostic of error order Currently the peerVerifyError test for QSslSocket makes an assumption about the order in which SSL errors are emitted by peerVerifyError. This assumption does not necessarily hold for non-OpenSSL backends. This change fixes this assumption, and also checks that HostNameMismatch was found both in the errors emitted by peerVerifyError and by sslErrors. Change-Id: I856d1ea43b36332db0f178d35fc14a4bb18ad673 Reviewed-by: Richard J. Moore --- .../network/ssl/qsslsocket/tst_qsslsocket.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index c2f004f756..295b60e739 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -1998,10 +1998,23 @@ void tst_QSslSocket::peerVerifyError() socket->connectToHostEncrypted(QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString(), 443); if (socket->waitForEncrypted(10000)) QSKIP("Skipping flaky test - See QTBUG-29941"); + + // check HostNameMismatch was emitted by peerVerifyError QVERIFY(!peerVerifyErrorSpy.isEmpty()); + SslErrorList peerErrors; + const QList &peerVerifyList = peerVerifyErrorSpy; + foreach (const QVariantList &args, peerVerifyList) + peerErrors << qvariant_cast(args.first()).error(); + QVERIFY(peerErrors.contains(QSslError::HostNameMismatch)); + + // check HostNameMismatch was emitted by sslErrors QVERIFY(!sslErrorsSpy.isEmpty()); - QCOMPARE(qvariant_cast(peerVerifyErrorSpy.last().at(0)).error(), QSslError::HostNameMismatch); - QCOMPARE(qvariant_cast >(sslErrorsSpy.at(0).at(0)).size(), peerVerifyErrorSpy.size()); + SslErrorList sslErrors; + foreach (const QSslError &err, qvariant_cast >(sslErrorsSpy.first().first())) + sslErrors << err.error(); + QVERIFY(peerErrors.contains(QSslError::HostNameMismatch)); + + QCOMPARE(sslErrors.size(), peerErrors.size()); } void tst_QSslSocket::disconnectFromHostWhenConnecting() From 9c4c0443389fd3dace13a04849c8c03481d6cbdb Mon Sep 17 00:00:00 2001 From: Maks Naumov Date: Wed, 3 Sep 2014 10:39:07 +0300 Subject: [PATCH 65/89] GraphicsView: Fix resolvePalette() for QGraphicsItem's children Use a proper function for that. Change-Id: I166ce44b8987d522cb01bae57009b2b862851b92 Reviewed-by: Andreas Aardal Hanssen --- src/widgets/graphicsview/qgraphicsitem_p.h | 2 +- src/widgets/graphicsview/qgraphicsscene.cpp | 4 ++-- .../qgraphicsitem/tst_qgraphicsitem.cpp | 17 +++++++++++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/widgets/graphicsview/qgraphicsitem_p.h b/src/widgets/graphicsview/qgraphicsitem_p.h index 4d1835f178..7e3a01ef8b 100644 --- a/src/widgets/graphicsview/qgraphicsitem_p.h +++ b/src/widgets/graphicsview/qgraphicsitem_p.h @@ -318,7 +318,7 @@ public: virtual void resolvePalette(uint inheritedMask) { for (int i = 0; i < children.size(); ++i) - children.at(i)->d_ptr->resolveFont(inheritedMask); + children.at(i)->d_ptr->resolvePalette(inheritedMask); } virtual bool isProxyWidget() const; diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp index 1cd162e6bb..df74352e2b 100644 --- a/src/widgets/graphicsview/qgraphicsscene.cpp +++ b/src/widgets/graphicsview/qgraphicsscene.cpp @@ -1608,9 +1608,9 @@ void QGraphicsScenePrivate::updatePalette(const QPalette &palette) // whose parent is not a widget. foreach (QGraphicsItem *item, q->items()) { if (!item->parentItem()) { - // Resolvefont for an item is a noop operation, but + // ResolvePalette for an item is a noop operation, but // every item can be a widget, or can have a widget - // childre. + // children. item->d_ptr->resolvePalette(palette.resolve()); } } diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp index c89b05616d..8847a5748f 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp @@ -461,6 +461,7 @@ private slots: void touchEventPropagation_data(); void touchEventPropagation(); void deviceCoordinateCache_simpleRotations(); + void resolvePaletteForItemChildren(); // task specific tests below me void task141694_textItemEnsureVisible(); @@ -11695,5 +11696,21 @@ void tst_QGraphicsItem::QTBUG_21618_untransformable_sceneTransform() QCOMPARE(item2_bottomright->deviceTransform(tx).map(QPointF()), QPointF(100, 300)); } +void tst_QGraphicsItem::resolvePaletteForItemChildren() +{ + QGraphicsScene scene; + QGraphicsRectItem item(0, 0, 50, -150); + scene.addItem(&item); + QGraphicsWidget widget; + widget.setParentItem(&item); + + QColor green(Qt::green); + QPalette paletteForScene = scene.palette(); + paletteForScene.setColor(QPalette::Active, QPalette::Window, green); + scene.setPalette(paletteForScene); + + QCOMPARE(widget.palette().color(QPalette::Active, QPalette::Window), green); +} + QTEST_MAIN(tst_QGraphicsItem) #include "tst_qgraphicsitem.moc" From d98df9e929bd53c1d72ded2eca4e2ade899d01ba Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Tue, 2 Sep 2014 09:42:31 +0200 Subject: [PATCH 66/89] Android: don't recreate surface on shutdown When we suspend the app, we destroy the surface to save resources. We don't want to create it again just as we are shutting down. Task-number: QTBUG-41072 Change-Id: I7a616249bee869b92716d0911201a80d73c2f8da Reviewed-by: Christian Stromme --- src/plugins/platforms/android/qandroideventdispatcher.h | 1 + .../platforms/android/qandroidplatformopenglwindow.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/plugins/platforms/android/qandroideventdispatcher.h b/src/plugins/platforms/android/qandroideventdispatcher.h index 284c5fd392..295763ce5b 100644 --- a/src/plugins/platforms/android/qandroideventdispatcher.h +++ b/src/plugins/platforms/android/qandroideventdispatcher.h @@ -73,6 +73,7 @@ class QAndroidEventDispatcherStopper { public: static QAndroidEventDispatcherStopper *instance(); + static bool stopped() {return !instance()->started; } void startAll(); void stopAll(); void addEventDispatcher(QAndroidEventDispatcher *dispatcher); diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp index 73c0a76dd7..d3fb22094a 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp @@ -44,6 +44,7 @@ #include "qandroidplatformscreen.h" #include "androidjnimain.h" +#include "qandroideventdispatcher.h" #include #include @@ -121,6 +122,9 @@ void QAndroidPlatformOpenGLWindow::setGeometry(const QRect &rect) EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config) { + if (QAndroidEventDispatcherStopper::stopped()) + return m_eglSurface; + QMutexLocker lock(&m_surfaceMutex); if (m_nativeSurfaceId == -1) { From 675d3548153223c6658fc4a84f252736846a0874 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Wed, 27 Aug 2014 15:40:42 +0200 Subject: [PATCH 67/89] Avoid deadlock when suspending device Don't wait for the GUI thread when it's already waiting for us. An application that uses the virtual keyboard may get an inputmethod query just when it is being suspended. If the GUI thread is already blocking on a semaphore at that point, waiting for the android thread, we really do not want to wait for the GUI thread... Task-number: QTBUG-40955 Change-Id: Iea2cf0dd058a41a897d596c4bcf16f0508adb20b Reviewed-by: Christian Stromme --- src/plugins/platforms/android/qandroidinputcontext.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index 5d47d2fda4..90eff615a2 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -45,6 +45,7 @@ #include "qandroidinputcontext.h" #include "androidjnimain.h" #include "androidjniinput.h" +#include "qandroideventdispatcher.h" #include #include #include @@ -995,8 +996,10 @@ Q_INVOKABLE QVariant QAndroidInputContext::queryFocusObjectUnsafe(Qt::InputMetho QVariant QAndroidInputContext::queryFocusObjectThreadSafe(Qt::InputMethodQuery query, QVariant argument) { - bool inMainThread = qGuiApp->thread() == QThread::currentThread(); + const bool inMainThread = qGuiApp->thread() == QThread::currentThread(); QVariant retval; + if (QAndroidEventDispatcherStopper::stopped() && !inMainThread) + return retval; QMetaObject::invokeMethod(this, "queryFocusObjectUnsafe", inMainThread ? Qt::DirectConnection : Qt::BlockingQueuedConnection, @@ -1010,12 +1013,15 @@ QVariant QAndroidInputContext::queryFocusObjectThreadSafe(Qt::InputMethodQuery q QSharedPointer QAndroidInputContext::focusObjectInputMethodQuery(Qt::InputMethodQueries queries) { #warning TODO make qGuiApp->focusObject() thread safe !!! + const bool inMainThread = qGuiApp->thread() == QThread::currentThread(); + if (QAndroidEventDispatcherStopper::stopped() && !inMainThread) + return QSharedPointer(); QObject *focusObject = qGuiApp->focusObject(); if (!focusObject) return QSharedPointer(); QSharedPointer ret = QSharedPointer(new QInputMethodQueryEvent(queries)); - if (qGuiApp->thread()==QThread::currentThread()) { + if (inMainThread) { QCoreApplication::sendEvent(focusObject, ret.data()); } else { QMetaObject::invokeMethod(this, From 2e667c9171f141c6ee0a279aae4479d4414c99f3 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Tue, 2 Sep 2014 15:52:35 +0200 Subject: [PATCH 68/89] qdoc: Highlight selected section / entry in the documentation This commit adds id tags with the anchor reference as the value to html entities for documentation section titles and function signatures, properties etc. for both C++ and QML documentation pages. Together with new CSS rules, we can dynamically highlight the title that the user clicked on. This helps to locate the item of interest on a crowded page or when the page cannot be scrolled down enough to place the selected item on top. Change-Id: I7d1db2ed4e12779e1a9e571996ee65c3befa4e7a Reviewed-by: Martin Smith Reviewed-by: Venugopal Shivashankar --- doc/global/template/style/offline.css | 16 +++++ doc/global/template/style/online.css | 16 +++++ src/tools/qdoc/htmlgenerator.cpp | 90 ++++++++++++++++----------- 3 files changed, 86 insertions(+), 36 deletions(-) diff --git a/doc/global/template/style/offline.css b/doc/global/template/style/offline.css index 7fc0d62fa6..5957e3840d 100644 --- a/doc/global/template/style/offline.css +++ b/doc/global/template/style/offline.css @@ -97,6 +97,10 @@ a[href*="http://"], a[href*="ftp://"], a[href*="https://"] { text-height: 24px; } +.flags:target { + background-color: #FFFFD6; +} + /* ------------------------------- NOTE styles @@ -327,6 +331,10 @@ h2, p.h2 { max-width: 99%; } +h2:target { + background-color: #F2F3D4; +} + h3 { font: 500 14px/1.2 Arial; font-weight: 100; @@ -353,6 +361,10 @@ h3.fn, span.fn { margin-top: 45px; } +h3.fn:target { + background-color: #F6F6D6; +} + .name { color: #1A1A1A } @@ -413,6 +425,10 @@ table, pre { color: #66666E; } + table tr:target { + background-color: #F6F6D6; + } + table thead { text-align: left; padding-left: 20px; diff --git a/doc/global/template/style/online.css b/doc/global/template/style/online.css index 0dc01d396b..5d0cd7ecfb 100644 --- a/doc/global/template/style/online.css +++ b/doc/global/template/style/online.css @@ -48,6 +48,10 @@ links text-height: 24px; } +.flags:target { + background-color: #FFFFD6; +} + /* ------------------------------- NOTE styles @@ -204,6 +208,10 @@ h2, p.h2 { overflow: hidden; } +h2:target { + background-color: #F2F3D4; +} + h3 { font: 500 14px/1.2 Arial; font-weight: 100; @@ -212,6 +220,10 @@ h3 { margin-top: 30px; } +h3.fn:target { + background-color: #F6F6D6; +} + h3.fn, span.fn { border-width: 1px; border-style: solid; @@ -293,6 +305,10 @@ table, pre { color: #66666E; } + table tr:target { + background-color: #F6F6D6; + } + table thead { text-align: left; padding-left: 20px; diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp index ae8206b8c3..243c8090db 100644 --- a/src/tools/qdoc/htmlgenerator.cpp +++ b/src/tools/qdoc/htmlgenerator.cpp @@ -996,10 +996,16 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark break; case Atom::SectionRight: break; - case Atom::SectionHeadingLeft: - out() << "string().toInt() + hOffset(relative)) + QLatin1Char('>'); + case Atom::SectionHeadingLeft: { + int unit = atom->string().toInt() + hOffset(relative); + out() << ""; inSectionHeading_ = true; break; + } case Atom::SectionHeadingRight: out() << "string().toInt() + hOffset(relative)) + ">\n"; inSectionHeading_ = false; @@ -1217,10 +1223,9 @@ void HtmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker) else { if (!s->members.isEmpty()) { // out() << "
\n"; - out() << "" << divNavTop << "\n"; - out() << "

" << protectEnc((*s).name) << "

\n"; + QString ref = registerRef((*s).name.toLower()); + out() << "" << divNavTop << "\n"; + out() << "

" << protectEnc((*s).name) << "

\n"; generateSection(s->members, inner, marker, CodeMarker::Summary); } if (!s->reimpMembers.isEmpty()) { @@ -1255,13 +1260,14 @@ void HtmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker) out() << "\n"; } - out() << "" << divNavTop << '\n'; + QString detailsRef = registerRef("details"); + out() << "" << divNavTop << '\n'; if (!inner->doc().isEmpty()) { generateExtractionMark(inner, DetailedDescriptionMark); //out() << "
\n" out() << "
\n" // QTBUG-9504 - << "

" << "Detailed Description" << "

\n"; + << "

" << "Detailed Description" << "

\n"; generateBody(inner, marker); out() << "
\n"; // QTBUG-9504 generateAlsoList(inner, marker); @@ -1366,16 +1372,18 @@ void HtmlGenerator::generateQmlTypePage(QmlClassNode* qcn, CodeMarker* marker) s = sections.constBegin(); while (s != sections.constEnd()) { - out() << "" << divNavTop << '\n'; - out() << "

" << protectEnc((*s).name) << "

\n"; + out() << "

" << protectEnc((*s).name) << "

\n"; generateQmlSummary(*s, qcn, marker); ++s; } generateExtractionMark(qcn, DetailedDescriptionMark); - out() << "" << divNavTop << '\n'; - out() << "

" << "Detailed Description" << "

\n"; + QString detailsRef = registerRef("details"); + out() << "" << divNavTop << '\n'; + out() << "

" << "Detailed Description" << "

\n"; generateBody(qcn, marker); ClassNode* cn = qcn->classNode(); if (cn) @@ -1500,8 +1508,9 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker) sections = marker->sections(dn, CodeMarker::Summary, CodeMarker::Okay); s = sections.constBegin(); while (s != sections.constEnd()) { - out() << "" << divNavTop << '\n'; - out() << "

" << protectEnc((*s).name) << "

\n"; + QString ref = registerRef((*s).name); + out() << "" << divNavTop << '\n'; + out() << "

" << protectEnc((*s).name) << "

\n"; generateSectionList(*s, dn, marker, CodeMarker::Summary); ++s; } @@ -1539,6 +1548,7 @@ void HtmlGenerator::generateCollectionNode(CollectionNode* cn, CodeMarker* marke QList
sections; QList
::const_iterator s; QString fullTitle = cn->fullTitle(); + QString ref; generateHeader(fullTitle, cn, marker); generateTableOfContents(cn,marker,0); @@ -1553,15 +1563,17 @@ void HtmlGenerator::generateCollectionNode(CollectionNode* cn, CodeMarker* marke NodeMap nm; cn->getMemberNamespaces(nm); if (!nm.isEmpty()) { - out() << "" << divNavTop << '\n'; - out() << "

Namespaces

\n"; + ref = registerRef("namespaces"); + out() << "" << divNavTop << '\n'; + out() << "

Namespaces

\n"; generateAnnotatedList(cn, marker, nm); } nm.clear(); cn->getMemberClasses(nm); if (!nm.isEmpty()) { - out() << "" << divNavTop << '\n'; - out() << "

Classes

\n"; + ref = registerRef("classes"); + out() << "" << divNavTop << '\n'; + out() << "

Classes

\n"; generateAnnotatedList(cn, marker, nm); } nm.clear(); @@ -1570,8 +1582,9 @@ void HtmlGenerator::generateCollectionNode(CollectionNode* cn, CodeMarker* marke sections = marker->sections(cn, CodeMarker::Summary, CodeMarker::Okay); s = sections.constBegin(); while (s != sections.constEnd()) { - out() << "" << divNavTop << '\n'; - out() << "

" << protectEnc((*s).name) << "

\n"; + ref = registerRef((*s).name); + out() << "" << divNavTop << '\n'; + out() << "

" << protectEnc((*s).name) << "

\n"; generateSectionList(*s, cn, marker, CodeMarker::Summary); ++s; } @@ -1579,9 +1592,10 @@ void HtmlGenerator::generateCollectionNode(CollectionNode* cn, CodeMarker* marke Text brief = cn->doc().briefText(); if (cn->isModule() && !brief.isEmpty()) { generateExtractionMark(cn, DetailedDescriptionMark); - out() << "" << divNavTop << '\n'; + ref = registerRef("details"); + out() << "" << divNavTop << '\n'; out() << "
\n"; // QTBUG-9504 - out() << "

" << "Detailed Description" << "

\n"; + out() << "

" << "Detailed Description" << "

\n"; } else { generateExtractionMark(cn, DetailedDescriptionMark); @@ -2509,9 +2523,10 @@ QString HtmlGenerator::generateQmlMemberFile(QmlClassNode* qcn, QList
::const_iterator s = sections.constBegin(); while (s != sections.constEnd()) { - out() << "" << divNavTop << '\n'; - out() << "

" << protectEnc((*s).name) << "

\n"; + out() << "

" << protectEnc((*s).name) << "

\n"; generateQmlSummary(*s, qcn, marker); ++s; } @@ -3815,13 +3830,14 @@ void HtmlGenerator::generateDetailedMember(const Node *node, generateMacRef(node, marker); #endif generateExtractionMark(node, MemberMark); + QString nodeRef = refForNode(node); if (node->type() == Node::Enum && (enume = static_cast(node))->flagsType()) { #ifdef GENERATE_MAC_REFS generateMacRef(enume->flagsType(), marker); #endif - out() << "

"; - out() << ""; + out() << "

"; + out() << ""; generateSynopsis(enume, relative, marker, CodeMarker::Detailed); out() << "
"; generateSynopsis(enume->flagsType(), @@ -3831,8 +3847,8 @@ void HtmlGenerator::generateDetailedMember(const Node *node, out() << "

\n"; } else { - out() << "

"; - out() << ""; + out() << "

"; + out() << ""; generateSynopsis(node, relative, marker, CodeMarker::Detailed); out() << "

" << divNavTop << '\n'; } @@ -4051,6 +4067,7 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node, #endif generateExtractionMark(node, MemberMark); out() << "
"; + QString nodeRef = refForNode(node); if (node->type() == Node::QmlPropertyGroup) { const QmlPropertyGroupNode* qpgn = static_cast(node); NodeList::ConstIterator p = qpgn->childNodes().constBegin(); @@ -4058,17 +4075,18 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node, out() << ""; QString heading = qpgn->name() + " group"; - out() << ""; + out() << ""; out() << ""; while (p != qpgn->childNodes().constEnd()) { if ((*p)->type() == Node::QmlProperty) { qpn = static_cast(*p); - out() << ""; + nodeRef = refForNode(qpn); + out() << ""; out() << "

"; - out() << ""; + out() << ""; out() << "" << heading << ""; out() << "

"; - out() << ""; + out() << ""; if (!qpn->isWritable()) out() << "read-only"; @@ -4086,7 +4104,7 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node, qpn = static_cast(node); out() << "

"; out() << ""; - out() << ""; + out() << ""; out() << "

"; out() << ""; if (!qpn->isReadOnlySet()) { @@ -4106,7 +4124,7 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node, const FunctionNode* qsn = static_cast(node); out() << "

"; out() << ""; - out() << ""; + out() << ""; out() << "

"; out() << ""; generateSynopsis(qsn,relative,marker,CodeMarker::Detailed,false); @@ -4118,7 +4136,7 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node, const FunctionNode* qshn = static_cast(node); out() << "

"; out() << ""; - out() << ""; + out() << ""; out() << "

"; out() << ""; generateSynopsis(qshn,relative,marker,CodeMarker::Detailed,false); @@ -4130,7 +4148,7 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node, const FunctionNode* qmn = static_cast(node); out() << "

"; out() << ""; - out() << ""; + out() << ""; out() << "

"; out() << ""; generateSynopsis(qmn,relative,marker,CodeMarker::Detailed,false); From 070fcf9ce1ef3c2912bd15f1f39db9740cc754c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeremy=20Lain=C3=A9?= Date: Wed, 3 Sep 2014 11:41:22 +0200 Subject: [PATCH 69/89] ssl: common certificate parser support for extensions This makes non-OpenSSL backends able to handle to certificate extensions. This also converts the Q_OS_WINRT #ifdef's in the unit test to QT_NO_OPENSSL as the behavior is the same for any non-OpenSSL backend. Change-Id: I6a8306dc5c97a659ec96063d5a59cee2ee9a63a9 Reviewed-by: Richard J. Moore --- src/network/ssl/qasn1element.cpp | 8 + src/network/ssl/qasn1element_p.h | 7 +- src/network/ssl/qsslcertificate.cpp | 150 ---------- src/network/ssl/qsslcertificate_p.h | 5 +- src/network/ssl/qsslcertificate_qt.cpp | 256 +++++++++++++++++- src/network/ssl/qsslkey_qt.cpp | 4 +- .../qsslcertificate/tst_qsslcertificate.cpp | 12 +- 7 files changed, 274 insertions(+), 168 deletions(-) diff --git a/src/network/ssl/qasn1element.cpp b/src/network/ssl/qasn1element.cpp index 78fffbf793..f3f280d863 100644 --- a/src/network/ssl/qasn1element.cpp +++ b/src/network/ssl/qasn1element.cpp @@ -56,6 +56,14 @@ static OidNameMap createOidMap() // used by unit tests oids.insert(oids.end(), QByteArrayLiteral("0.9.2342.19200300.100.1.5"), QByteArrayLiteral("favouriteDrink")); oids.insert(oids.end(), QByteArrayLiteral("1.2.840.113549.1.9.1"), QByteArrayLiteral("emailAddress")); + oids.insert(oids.end(), QByteArrayLiteral("1.3.6.1.5.5.7.1.1"), QByteArrayLiteral("authorityInfoAccess")); + oids.insert(oids.end(), QByteArrayLiteral("1.3.6.1.5.5.7.48.1"), QByteArrayLiteral("OCSP")); + oids.insert(oids.end(), QByteArrayLiteral("1.3.6.1.5.5.7.48.2"), QByteArrayLiteral("caIssuers")); + oids.insert(oids.end(), QByteArrayLiteral("2.5.29.14"), QByteArrayLiteral("subjectKeyIdentifier")); + oids.insert(oids.end(), QByteArrayLiteral("2.5.29.15"), QByteArrayLiteral("keyUsage")); + oids.insert(oids.end(), QByteArrayLiteral("2.5.29.17"), QByteArrayLiteral("subjectAltName")); + oids.insert(oids.end(), QByteArrayLiteral("2.5.29.19"), QByteArrayLiteral("basicConstraints")); + oids.insert(oids.end(), QByteArrayLiteral("2.5.29.35"), QByteArrayLiteral("authorityKeyIdentifier")); oids.insert(oids.end(), QByteArrayLiteral("2.5.4.10"), QByteArrayLiteral("O")); oids.insert(oids.end(), QByteArrayLiteral("2.5.4.11"), QByteArrayLiteral("OU")); oids.insert(oids.end(), QByteArrayLiteral("2.5.4.12"), QByteArrayLiteral("title")); diff --git a/src/network/ssl/qasn1element_p.h b/src/network/ssl/qasn1element_p.h index b4445dacfd..36a7c90de3 100644 --- a/src/network/ssl/qasn1element_p.h +++ b/src/network/ssl/qasn1element_p.h @@ -59,6 +59,9 @@ QT_BEGIN_NAMESPACE +#define RSA_ENCRYPTION_OID QByteArrayLiteral("1.2.840.113549.1.1.1") +#define DSA_ENCRYPTION_OID QByteArrayLiteral("1.2.840.10040.4.1") + class Q_AUTOTEST_EXPORT QAsn1Element { public: @@ -78,10 +81,6 @@ public: SequenceType = 0x30, SetType = 0x31, - // application - Rfc822NameType = 0x81, - DnsNameType = 0x82, - // context specific Context0Type = 0xA0, Context3Type = 0xA3 diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index bae78f4347..47ea3343ea 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -122,7 +122,6 @@ #include "qsslcertificate.h" #include "qsslcertificate_p.h" -#include "qasn1element_p.h" #include "qsslkey_p.h" #include @@ -642,155 +641,6 @@ static const char *certificate_blacklist[] = { 0 }; -bool QSslCertificatePrivate::parse(const QByteArray &data) -{ -#ifndef QT_NO_OPENSSL - Q_UNUSED(data); -#else - QAsn1Element root; - - QDataStream dataStream(data); - if (!root.read(dataStream) || root.type() != QAsn1Element::SequenceType) - return false; - - QDataStream rootStream(root.value()); - QAsn1Element cert; - if (!cert.read(rootStream) || cert.type() != QAsn1Element::SequenceType) - return false; - - // version or serial number - QAsn1Element elem; - QDataStream certStream(cert.value()); - if (!elem.read(certStream)) - return false; - - if (elem.type() == QAsn1Element::Context0Type) { - QDataStream versionStream(elem.value()); - if (!elem.read(versionStream) || elem.type() != QAsn1Element::IntegerType) - return false; - - versionString = QByteArray::number(elem.value()[0] + 1); - if (!elem.read(certStream)) - return false; - } else { - versionString = QByteArray::number(1); - } - - // serial number - if (elem.type() != QAsn1Element::IntegerType) - return false; - - QByteArray hexString; - hexString.reserve(elem.value().size() * 3); - for (int a = 0; a < elem.value().size(); ++a) { - const quint8 b = elem.value().at(a); - if (b || !hexString.isEmpty()) { // skip leading zeros - hexString += QByteArray::number(b, 16).rightJustified(2, '0'); - hexString += ':'; - } - } - hexString.chop(1); - serialNumberString = hexString; - - // algorithm ID - if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType) - return false; - - //qDebug() << "algorithm ID" << elem.type() << elem.length << elem.value().toHex(); - - // issuer info - if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType) - return false; - - QByteArray issuerDer = data.mid(dataStream.device()->pos() - elem.value().length(), elem.value().length()); - issuerInfo = elem.toInfo(); - - // validity period - if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType) - return false; - - QDataStream validityStream(elem.value()); - if (!elem.read(validityStream) || (elem.type() != QAsn1Element::UtcTimeType && elem.type() != QAsn1Element::GeneralizedTimeType)) - return false; - - notValidBefore = elem.toDateTime(); - if (!elem.read(validityStream) || (elem.type() != QAsn1Element::UtcTimeType && elem.type() != QAsn1Element::GeneralizedTimeType)) - return false; - - notValidAfter = elem.toDateTime(); - - // subject name - if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType) - return false; - - QByteArray subjectDer = data.mid(dataStream.device()->pos() - elem.value().length(), elem.value().length()); - subjectInfo = elem.toInfo(); - subjectMatchesIssuer = issuerDer == subjectDer; - - // public key - qint64 keyStart = certStream.device()->pos(); - if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType) - return false; - - publicKeyDerData.resize(certStream.device()->pos() - keyStart); - QDataStream keyStream(elem.value()); - if (!elem.read(keyStream) || elem.type() != QAsn1Element::SequenceType) - return false; - - - // key algorithm - if (!elem.read(elem.value()) || elem.type() != QAsn1Element::ObjectIdentifierType) - return false; - - const QByteArray oid = elem.toObjectId(); - if (oid == "1.2.840.113549.1.1.1") - publicKeyAlgorithm = QSsl::Rsa; - else if (oid == "1.2.840.10040.4.1") - publicKeyAlgorithm = QSsl::Dsa; - else - publicKeyAlgorithm = QSsl::Opaque; - - certStream.device()->seek(keyStart); - certStream.readRawData(publicKeyDerData.data(), publicKeyDerData.size()); - - // extensions - while (elem.read(certStream)) { - if (elem.type() == QAsn1Element::Context3Type) { - if (elem.read(elem.value()) && elem.type() == QAsn1Element::SequenceType) { - QDataStream extStream(elem.value()); - while (elem.read(extStream) && elem.type() == QAsn1Element::SequenceType) { - QAsn1Element oidElem, valElem; - QDataStream seqStream(elem.value()); - if (oidElem.read(seqStream) && oidElem.type() == QAsn1Element::ObjectIdentifierType && - valElem.read(seqStream) && valElem.type() == QAsn1Element::OctetStringType) { - // alternative name - if (oidElem.toObjectId() == QByteArray("2.5.29.17")) { - QAsn1Element sanElem; - if (sanElem.read(valElem.value()) && sanElem.type() == QAsn1Element::SequenceType) { - QDataStream nameStream(sanElem.value()); - QAsn1Element nameElem; - while (nameElem.read(nameStream)) { - if (nameElem.type() == QAsn1Element::Rfc822NameType) { - subjectAlternativeNames.insert(QSsl::EmailEntry, QString::fromLatin1(nameElem.value(), nameElem.value().size())); - } else if (nameElem.type() == QAsn1Element::DnsNameType) { - subjectAlternativeNames.insert(QSsl::DnsEntry, QString::fromLatin1(nameElem.value(), nameElem.value().size())); - } - } - } - } - } - } - } - } - } - - derData = data.left(dataStream.device()->pos()); - null = false; - -#endif // QT_NO_OPENSSL - return true; -} - bool QSslCertificatePrivate::isBlacklisted(const QSslCertificate &certificate) { for (int a = 0; certificate_blacklist[a] != 0; a++) { diff --git a/src/network/ssl/qsslcertificate_p.h b/src/network/ssl/qsslcertificate_p.h index 472553c30c..b0c99e545d 100644 --- a/src/network/ssl/qsslcertificate_p.h +++ b/src/network/ssl/qsslcertificate_p.h @@ -109,13 +109,16 @@ public: QSsl::KeyAlgorithm publicKeyAlgorithm; QByteArray publicKeyDerData; QMultiMap subjectAlternativeNames; + QList extensions; QByteArray derData; + + bool parse(const QByteArray &data); + bool parseExtension(const QByteArray &data, QSslCertificateExtension *extension); #endif X509 *x509; void init(const QByteArray &data, QSsl::EncodingFormat format); - bool parse(const QByteArray &data); static QByteArray asn1ObjectId(ASN1_OBJECT *object); static QByteArray asn1ObjectName(ASN1_OBJECT *object); diff --git a/src/network/ssl/qsslcertificate_qt.cpp b/src/network/ssl/qsslcertificate_qt.cpp index 391ee6f7f9..6ea78a408b 100644 --- a/src/network/ssl/qsslcertificate_qt.cpp +++ b/src/network/ssl/qsslcertificate_qt.cpp @@ -47,9 +47,17 @@ #include "qsslkey_p.h" #include "qsslcertificateextension.h" #include "qsslcertificateextension_p.h" +#include "qasn1element_p.h" QT_BEGIN_NAMESPACE +enum GeneralNameType +{ + Rfc822NameType = 0x81, + DnsNameType = 0x82, + UniformResourceIdentifierType = 0x86 +}; + bool QSslCertificate::operator==(const QSslCertificate &other) const { if (d == other.d) @@ -150,8 +158,7 @@ QSslKey QSslCertificate::publicKey() const QList QSslCertificate::extensions() const { - Q_UNIMPLEMENTED(); - return QList(); + return d->extensions; } #define BEGINCERTSTRING "-----BEGIN CERTIFICATE-----" @@ -263,4 +270,249 @@ QList QSslCertificatePrivate::certificatesFromDer(const QByteAr return certificates; } +static QByteArray colonSeparatedHex(const QByteArray &value) +{ + QByteArray hexString; + hexString.reserve(value.size() * 3); + for (int a = 0; a < value.size(); ++a) { + const quint8 b = value.at(a); + if (b || !hexString.isEmpty()) { // skip leading zeros + hexString += QByteArray::number(b, 16).rightJustified(2, '0'); + hexString += ':'; + } + } + hexString.chop(1); + return hexString; +} + +bool QSslCertificatePrivate::parse(const QByteArray &data) +{ + QAsn1Element root; + + QDataStream dataStream(data); + if (!root.read(dataStream) || root.type() != QAsn1Element::SequenceType) + return false; + + QDataStream rootStream(root.value()); + QAsn1Element cert; + if (!cert.read(rootStream) || cert.type() != QAsn1Element::SequenceType) + return false; + + // version or serial number + QAsn1Element elem; + QDataStream certStream(cert.value()); + if (!elem.read(certStream)) + return false; + + if (elem.type() == QAsn1Element::Context0Type) { + QDataStream versionStream(elem.value()); + if (!elem.read(versionStream) || elem.type() != QAsn1Element::IntegerType) + return false; + + versionString = QByteArray::number(elem.value()[0] + 1); + if (!elem.read(certStream)) + return false; + } else { + versionString = QByteArray::number(1); + } + + // serial number + if (elem.type() != QAsn1Element::IntegerType) + return false; + serialNumberString = colonSeparatedHex(elem.value()); + + // algorithm ID + if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType) + return false; + + // issuer info + if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType) + return false; + + QByteArray issuerDer = data.mid(dataStream.device()->pos() - elem.value().length(), elem.value().length()); + issuerInfo = elem.toInfo(); + + // validity period + if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType) + return false; + + QDataStream validityStream(elem.value()); + if (!elem.read(validityStream) || (elem.type() != QAsn1Element::UtcTimeType && elem.type() != QAsn1Element::GeneralizedTimeType)) + return false; + + notValidBefore = elem.toDateTime(); + if (!elem.read(validityStream) || (elem.type() != QAsn1Element::UtcTimeType && elem.type() != QAsn1Element::GeneralizedTimeType)) + return false; + + notValidAfter = elem.toDateTime(); + + // subject name + if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType) + return false; + + QByteArray subjectDer = data.mid(dataStream.device()->pos() - elem.value().length(), elem.value().length()); + subjectInfo = elem.toInfo(); + subjectMatchesIssuer = issuerDer == subjectDer; + + // public key + qint64 keyStart = certStream.device()->pos(); + if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType) + return false; + + publicKeyDerData.resize(certStream.device()->pos() - keyStart); + QDataStream keyStream(elem.value()); + if (!elem.read(keyStream) || elem.type() != QAsn1Element::SequenceType) + return false; + + + // key algorithm + if (!elem.read(elem.value()) || elem.type() != QAsn1Element::ObjectIdentifierType) + return false; + + const QByteArray oid = elem.toObjectId(); + if (oid == RSA_ENCRYPTION_OID) + publicKeyAlgorithm = QSsl::Rsa; + else if (oid == RSA_ENCRYPTION_OID) + publicKeyAlgorithm = QSsl::Dsa; + else + publicKeyAlgorithm = QSsl::Opaque; + + certStream.device()->seek(keyStart); + certStream.readRawData(publicKeyDerData.data(), publicKeyDerData.size()); + + // extensions + while (elem.read(certStream)) { + if (elem.type() == QAsn1Element::Context3Type) { + if (elem.read(elem.value()) && elem.type() == QAsn1Element::SequenceType) { + QDataStream extStream(elem.value()); + while (elem.read(extStream) && elem.type() == QAsn1Element::SequenceType) { + QSslCertificateExtension extension; + if (!parseExtension(elem.value(), &extension)) + return false; + extensions << extension; + + if (extension.oid() == QLatin1String("2.5.29.17")) { + // subjectAltName + QAsn1Element sanElem; + if (sanElem.read(extension.value().toByteArray()) && sanElem.type() == QAsn1Element::SequenceType) { + QDataStream nameStream(sanElem.value()); + QAsn1Element nameElem; + while (nameElem.read(nameStream)) { + if (nameElem.type() == Rfc822NameType) { + subjectAlternativeNames.insert(QSsl::EmailEntry, QString::fromLatin1(nameElem.value(), nameElem.value().size())); + } else if (nameElem.type() == DnsNameType) { + subjectAlternativeNames.insert(QSsl::DnsEntry, QString::fromLatin1(nameElem.value(), nameElem.value().size())); + } + } + } + } + } + } + } + } + + derData = data.left(dataStream.device()->pos()); + null = false; + return true; +} + +bool QSslCertificatePrivate::parseExtension(const QByteArray &data, QSslCertificateExtension *extension) +{ + bool ok; + bool critical = false; + QAsn1Element oidElem, valElem; + + QDataStream seqStream(data); + + // oid + if (!oidElem.read(seqStream) || oidElem.type() != QAsn1Element::ObjectIdentifierType) + return false; + const QByteArray oid = oidElem.toObjectId(); + + // critical and value + if (!valElem.read(seqStream)) + return false; + if (valElem.type() == QAsn1Element::BooleanType) { + critical = valElem.toBool(&ok); + if (!ok || !valElem.read(seqStream)) + return false; + } + if (valElem.type() != QAsn1Element::OctetStringType) + return false; + + // interpret value + QAsn1Element val; + bool supported = true; + QVariant value; + if (oid == QByteArrayLiteral("1.3.6.1.5.5.7.1.1")) { + // authorityInfoAccess + if (!val.read(valElem.value()) || val.type() != QAsn1Element::SequenceType) + return false; + QVariantMap result; + foreach (const QAsn1Element &el, val.toVector()) { + QVector items = el.toVector(); + if (items.size() != 2) + return false; + const QString key = QString::fromLatin1(items.at(0).toObjectName()); + switch (items.at(1).type()) { + case Rfc822NameType: + case DnsNameType: + case UniformResourceIdentifierType: + result[key] = QString::fromLatin1(items.at(1).value(), items.at(1).value().size()); + break; + } + } + value = result; + } else if (oid == QByteArrayLiteral("2.5.29.14")) { + // subjectKeyIdentifier + if (!val.read(valElem.value()) || val.type() != QAsn1Element::OctetStringType) + return false; + value = colonSeparatedHex(val.value()).toUpper(); + } else if (oid == QByteArrayLiteral("2.5.29.19")) { + // basicConstraints + if (!val.read(valElem.value()) || val.type() != QAsn1Element::SequenceType) + return false; + + QVariantMap result; + QVector items = val.toVector(); + if (items.size() > 0) { + result[QStringLiteral("ca")] = items.at(0).toBool(&ok); + if (!ok) + return false; + } else { + result[QStringLiteral("ca")] = false; + } + if (items.size() > 1) { + result[QStringLiteral("pathLenConstraint")] = items.at(1).toInteger(&ok); + if (!ok) + return false; + } + value = result; + } else if (oid == QByteArrayLiteral("2.5.29.35")) { + // authorityKeyIdentifier + if (!val.read(valElem.value()) || val.type() != QAsn1Element::SequenceType) + return false; + QVariantMap result; + foreach (const QAsn1Element &el, val.toVector()) { + if (el.type() == 0x80) { + result[QStringLiteral("keyid")] = el.value().toHex(); + } else if (el.type() == 0x82) { + result[QStringLiteral("serial")] = colonSeparatedHex(el.value()); + } + } + value = result; + } else { + supported = false; + value = valElem.value(); + } + + extension->d->critical = critical; + extension->d->supported = supported; + extension->d->oid = QString::fromLatin1(oid); + extension->d->name = QString::fromLatin1(oidElem.toObjectName()); + extension->d->value = value; + + return true; +} + QT_END_NAMESPACE diff --git a/src/network/ssl/qsslkey_qt.cpp b/src/network/ssl/qsslkey_qt.cpp index c14cf0250c..bc1ebc3c08 100644 --- a/src/network/ssl/qsslkey_qt.cpp +++ b/src/network/ssl/qsslkey_qt.cpp @@ -133,7 +133,7 @@ void QSslKeyPrivate::decodeDer(const QByteArray &der, bool deepClear) if (infoItems.size() < 2 || infoItems[0].type() != QAsn1Element::ObjectIdentifierType) return; if (algorithm == QSsl::Rsa) { - if (infoItems[0].toObjectId() != "1.2.840.113549.1.1.1") + if (infoItems[0].toObjectId() != RSA_ENCRYPTION_OID) return; // key data if (!elem.read(keyStream) || elem.type() != QAsn1Element::BitStringType || elem.value().isEmpty()) @@ -144,7 +144,7 @@ void QSslKeyPrivate::decodeDer(const QByteArray &der, bool deepClear) return; keyLength = numberOfBits(elem.value()); } else if (algorithm == QSsl::Dsa) { - if (infoItems[0].toObjectId() != "1.2.840.10040.4.1") + if (infoItems[0].toObjectId() != DSA_ENCRYPTION_OID) return; if (infoItems[1].type() != QAsn1Element::SequenceType) return; diff --git a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp index 56530acb14..229ce4abb5 100644 --- a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp +++ b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp @@ -928,7 +928,7 @@ void tst_QSslCertificate::toText() QString txtcert = cert.toText(); -#ifdef Q_OS_WINRT +#ifdef QT_NO_OPENSSL QEXPECT_FAIL("", "QTBUG-40884: QSslCertificate::toText is not implemented on WinRT", Continue); #endif QVERIFY(QString::fromLatin1(txt098) == txtcert || @@ -976,7 +976,7 @@ void tst_QSslCertificate::verify() qPrintable(QString("errors: %1").arg(toString(errors))) \ ) -#ifdef Q_OS_WINRT +#ifdef QT_NO_OPENSSL QEXPECT_FAIL("", "QTBUG-40884: WinRT API does not yet support verifying a chain", Abort); #endif // Empty chain is unspecified error @@ -1060,9 +1060,6 @@ void tst_QSslCertificate::extensions() QSslCertificate cert = certList[0]; QList extensions = cert.extensions(); -#ifdef Q_OS_WINRT - QEXPECT_FAIL("", "QTBUG-40884: WinRT API does not support extensions information", Abort); -#endif QVERIFY(extensions.count() == 9); int unknown_idx = -1; @@ -1161,9 +1158,6 @@ void tst_QSslCertificate::extensionsCritical() QSslCertificate cert = certList[0]; QList extensions = cert.extensions(); -#ifdef Q_OS_WINRT - QEXPECT_FAIL("", "QTBUG-40884: WinRT API does not support extensions information", Abort); -#endif QVERIFY(extensions.count() == 9); int basic_constraints_idx = -1; @@ -1314,7 +1308,7 @@ void tst_QSslCertificate::pkcs12() QSslCertificate cert; QList caCerts; -#ifdef Q_OS_WINRT +#ifdef QT_NO_OPENSSL QEXPECT_FAIL("", "QTBUG-40884: WinRT API does not support pkcs12 imports", Abort); #endif ok = QSslCertificate::importPKCS12(&f, &key, &cert, &caCerts); From eac2876d55732696991c4629e6bd88e302a72f56 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 23 Jul 2014 14:01:38 +0200 Subject: [PATCH 70/89] Windows: Move dock windows automatically when screen is disconnected. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Windows does not automatically move WS_EX_TOOLWINDOW type windows. Task-number: QTBUG-39320 Change-Id: If9804f32beb534a27ba649abf5eaceb686af8f50 Reviewed-by: Björn Breitmeyer Reviewed-by: Joerg Bornemann --- .../platforms/windows/qwindowsscreen.cpp | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index 796975122e..f491b51aa8 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -429,6 +429,23 @@ static inline int indexOfMonitor(const QList &screenData, return -1; } +// Move a window to a new virtual screen, accounting for varying sizes. +static void moveToVirtualScreen(QWindow *w, const QScreen *newScreen) +{ + QRect geometry = w->geometry(); + const QRect oldScreenGeometry = w->screen()->geometry(); + const QRect newScreenGeometry = newScreen->geometry(); + QPoint relativePosition = geometry.topLeft() - oldScreenGeometry.topLeft(); + if (oldScreenGeometry.size() != newScreenGeometry.size()) { + const qreal factor = + qreal(QPoint(newScreenGeometry.width(), newScreenGeometry.height()).manhattanLength()) / + qreal(QPoint(oldScreenGeometry.width(), oldScreenGeometry.height()).manhattanLength()); + relativePosition = (QPointF(relativePosition) * factor).toPoint(); + } + geometry.moveTopLeft(relativePosition); + w->setGeometry(geometry); +} + void QWindowsScreenManager::removeScreen(int index) { qCDebug(lcQpaWindows) << "Removing Monitor:" << m_screens.at(index)->data(); @@ -439,11 +456,18 @@ void QWindowsScreenManager::removeScreen(int index) // event, but unfortunately after the screen destruction signal. To prevent // QtGui from automatically hiding the QWindow, pretend all Windows move to // the primary screen first (which is likely the correct, final screen). + // QTBUG-39320: Windows does not automatically move WS_EX_TOOLWINDOW (dock) windows; + // move those manually. if (screen != primaryScreen) { unsigned movedWindowCount = 0; foreach (QWindow *w, QGuiApplication::topLevelWindows()) { if (w->screen() == screen && w->handle() && w->type() != Qt::Desktop) { - QWindowSystemInterface::handleWindowScreenChanged(w, primaryScreen); + if (w->isVisible() && w->windowState() != Qt::WindowMinimized + && (QWindowsWindow::baseWindowOf(w)->exStyle() & WS_EX_TOOLWINDOW)) { + moveToVirtualScreen(w, primaryScreen); + } else { + QWindowSystemInterface::handleWindowScreenChanged(w, primaryScreen); + } ++movedWindowCount; } } From f721a85b1e2a5c84a1a1a4d3f5b1c7fad7de854b Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Mon, 1 Sep 2014 17:35:35 +0400 Subject: [PATCH 71/89] xcb: fix coordinates of touch points Fix conversion from FP1616 to qreal. Use 16-bit mask 0xFFFF instead of 8-bit mask 0xFF. Change-Id: I0ee39b2e298b7ff7d7a67981925374d6a18f1474 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 84d00d0e09..60a36a8da1 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -413,7 +413,7 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id) #if defined(XCB_USE_XINPUT21) || !defined(QT_NO_TABLETEVENT) static qreal fixed1616ToReal(FP1616 val) { - return (qreal(val >> 16)) + (val & 0xFF) / (qreal)0xFF; + return (qreal(val >> 16)) + (val & 0xFFFF) / (qreal)0xFFFF; } #endif // defined(XCB_USE_XINPUT21) || !defined(QT_NO_TABLETEVENT) From 50e1733dfac8e0810a8a8aace7e9078322965167 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 4 Sep 2014 15:14:06 +0200 Subject: [PATCH 72/89] Bump version of QWidget geometry serialization to 2.0 It was decided not to port the handling of the saved screen size to Qt 4.8, so, bump the major version to ensure Qt 4.8 bails out. Task-number: QTBUG-38858 Change-Id: Ia870519553172cd383830d9a722b0fada180ee1b Reviewed-by: Alessandro Portale --- src/widgets/kernel/qwidget.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 21278a0ba9..65978ef562 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -7213,9 +7213,9 @@ QByteArray QWidget::saveGeometry() const const quint32 magicNumber = 0x1D9D0CB; // Version history: // - Qt 4.2 - 4.8.6, 5.0 - 5.3 : Version 1.0 - // - Qt 4.8.6 - today, 5.4 - today: Version 1.1, save screen width in addition to check for high DPI scaling. - quint16 majorVersion = 1; - quint16 minorVersion = 1; + // - Qt 4.8.6 - today, 5.4 - today: Version 2.0, save screen width in addition to check for high DPI scaling. + quint16 majorVersion = 2; + quint16 minorVersion = 0; const int screenNumber = QApplication::desktop()->screenNumber(this); stream << magicNumber << majorVersion @@ -7270,13 +7270,13 @@ bool QWidget::restoreGeometry(const QByteArray &geometry) if (storedMagicNumber != magicNumber) return false; - const quint16 currentMajorVersion = 1; + const quint16 currentMajorVersion = 2; quint16 majorVersion = 0; quint16 minorVersion = 0; stream >> majorVersion >> minorVersion; - if (majorVersion != currentMajorVersion) + if (majorVersion > currentMajorVersion) return false; // (Allow all minor versions.) @@ -7293,7 +7293,7 @@ bool QWidget::restoreGeometry(const QByteArray &geometry) >> maximized >> fullScreen; - if (majorVersion > 1 || minorVersion >= 1) + if (majorVersion > 1) stream >> restoredScreenWidth; const QDesktopWidget * const desktop = QApplication::desktop(); From 3cae7dcc5af53bacbf2e181092895c7b27439bca Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 16 May 2014 16:53:14 +0200 Subject: [PATCH 73/89] Use expiry_date field to check for evaluation timespan Use the new dedicated field instead of just assuming that the evaluation timespan is buildtime + 30 days. Change-Id: Ibf4078f030ea609d823fe01889a106a5da345817 Reviewed-by: Janne Anttila Reviewed-by: Iikka Eklund --- src/corelib/kernel/qtcore_eval.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qtcore_eval.cpp b/src/corelib/kernel/qtcore_eval.cpp index a5c4c36638..c938e0fb5b 100644 --- a/src/corelib/kernel/qtcore_eval.cpp +++ b/src/corelib/kernel/qtcore_eval.cpp @@ -119,9 +119,11 @@ static EvaluationStatus qt_eval_is_supported() static int qt_eval_days_left() { + const char *expiry_date = const_cast(qt_eval_expiry_date + 12); + QDate today = QDate::currentDate(); - QDate build = QLibraryInfo::buildDate(); - return qMax(-1, today.daysTo(build) + 30); + QDate lastday = QDate::fromString(QString::fromLatin1(expiry_date), Qt::ISODate); + return today.daysTo(lastday); } static bool qt_eval_is_expired() From 0e2c32931387cd89d97011ff1b9f9baed0975ccc Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 4 Sep 2014 08:05:13 +0200 Subject: [PATCH 74/89] Remove GLdouble and GL_DOUBLE typedefs for OpenGL ES 2. We have no business defining types which come from another library. These originally stem from the S60 port without further explanation and Qt and its examples today compile without them, so remove them. Change-Id: I683ea897c00ab3a1f7c809c45352fe590ae9a41f Reviewed-by: Laszlo Agocs --- src/gui/opengl/qopengl.h | 6 ------ src/gui/opengl/qopenglfunctions.h | 2 ++ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/gui/opengl/qopengl.h b/src/gui/opengl/qopengl.h index 65bfc7f868..56e99ee8b8 100644 --- a/src/gui/opengl/qopengl.h +++ b/src/gui/opengl/qopengl.h @@ -117,12 +117,6 @@ typedef char GLchar; # include # endif // Q_OS_MAC -# ifndef GL_DOUBLE -# define GL_DOUBLE GL_FLOAT -# endif -# ifndef GLdouble -typedef GLfloat GLdouble; -# endif #else // non-ES2 platforms # if defined(Q_OS_MAC) # include diff --git a/src/gui/opengl/qopenglfunctions.h b/src/gui/opengl/qopenglfunctions.h index de1de39db2..b9e7523aad 100644 --- a/src/gui/opengl/qopenglfunctions.h +++ b/src/gui/opengl/qopenglfunctions.h @@ -563,8 +563,10 @@ struct QOpenGLFunctionsPrivate void (QOPENGLF_APIENTRYP VertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr); // Special non-ES OpenGL variants, not to be called directly +#ifndef QT_OPENGL_ES_2 void (QOPENGLF_APIENTRYP ClearDepth)(GLdouble depth); void (QOPENGLF_APIENTRYP DepthRange)(GLdouble zNear, GLdouble zFar); +#endif }; // GLES2 + OpenGL1 common subset From a3421d1ba670a25c502f5e57d16394eefaa433f3 Mon Sep 17 00:00:00 2001 From: Maks Naumov Date: Fri, 5 Sep 2014 12:29:02 +0300 Subject: [PATCH 75/89] QDateTimeParser: remove unused local variables Change-Id: Id78fde8a720961c448d1aa3983ad296974796fdf Reviewed-by: Marc Mutz --- src/corelib/tools/qdatetimeparser.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index fb5c5f5943..edb4f4e048 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -749,7 +749,6 @@ int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionInde break; } if (state != Invalid) { - QString str = text; text.replace(index, used, sectiontext.left(used)); } break; } @@ -770,7 +769,6 @@ int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionInde if (num != -1) { state = (used == sectiontext.size() ? Acceptable : Intermediate); - QString str = text; text.replace(index, used, sectiontext.left(used)); } else { state = Intermediate; From 93560de9de6ce1a8357c7ba4bd26becee4d35d99 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Mon, 18 Aug 2014 19:42:36 +0200 Subject: [PATCH 76/89] kms: Move debug output behind a category. Change-Id: I5b2bb8631a33b577afca1a0852abe4cabae1e254 Reviewed-by: Kai Koehne --- src/plugins/platforms/kms/qkmsscreen.cpp | 9 +++++---- src/plugins/platforms/kms/qkmsscreen.h | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/kms/qkmsscreen.cpp b/src/plugins/platforms/kms/qkmsscreen.cpp index a930aa6545..3368af046f 100644 --- a/src/plugins/platforms/kms/qkmsscreen.cpp +++ b/src/plugins/platforms/kms/qkmsscreen.cpp @@ -38,7 +38,6 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -//#include #include "qkmsscreen.h" #include "qkmscursor.h" @@ -52,6 +51,8 @@ QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.kms.screen") + //Fallback mode (taken from Wayland DRM demo compositor) static drmModeModeInfo builtin_1024x768 = { 63500, //clock @@ -148,7 +149,7 @@ void QKmsScreen::initializeScreenMode(const drmModeRes *resources, const drmMode m_crtcId = resources->crtcs[i]; m_mode = *mode; m_geometry = QRect(0, 0, m_mode.hdisplay, m_mode.vdisplay); - qDebug() << "kms initialized with geometry" << m_geometry; + qCDebug(lcQpaScreen) << "kms initialized with geometry" << m_geometry; m_depth = 32; m_format = QImage::Format_RGB32; m_physicalSize = QSizeF(connector->mmWidth, connector->mmHeight); @@ -158,7 +159,7 @@ void QKmsScreen::initializeScreenMode(const drmModeRes *resources, const drmMode GBM_BO_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); - qDebug() << "created gbm surface" << m_gbmSurface << m_mode.hdisplay << m_mode.vdisplay; + qCDebug(lcQpaScreen) << "created gbm surface" << m_gbmSurface << m_mode.hdisplay << m_mode.vdisplay; //Cleanup drmModeFreeEncoder(encoder); } @@ -180,7 +181,7 @@ void QKmsScreen::initializeWithFormat(const QSurfaceFormat &format) EGLConfig config = q_configFromGLFormat(display, tweakFormat(format), true); m_eglWindowSurface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)m_gbmSurface, NULL); - qDebug() << "created window surface"; + qCDebug(lcQpaScreen) << "created window surface"; } void QKmsScreen::swapBuffers() diff --git a/src/plugins/platforms/kms/qkmsscreen.h b/src/plugins/platforms/kms/qkmsscreen.h index 1fa8dbb763..58237877a6 100644 --- a/src/plugins/platforms/kms/qkmsscreen.h +++ b/src/plugins/platforms/kms/qkmsscreen.h @@ -56,11 +56,14 @@ extern "C" { #include #include #include +#include #include QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen) + class QKmsCursor; class QKmsDevice; class QKmsContext; From 357f80878d56d9b612724533fa7ad9d25c7ec100 Mon Sep 17 00:00:00 2001 From: Adam Majer Date: Fri, 5 Sep 2014 15:30:49 -0500 Subject: [PATCH 77/89] Bump Q_COMPILER_INITIALIZER_LISTS to GCC 4.5 While GCC 4.4 has the required header, it is missing important typedefs requiring use of pointers instead. This is acceptable if only used in one or two places, but a quick search through the source code lists quite a few usages of const_iterator typedef. $ git grep -c initializer_list\<.\*\>::const_iterator src/corelib/global/qflags.h:2 src/corelib/json/qjsonarray.h:1 src/corelib/json/qjsonobject.h:1 src/corelib/tools/qhash.h:2 src/corelib/tools/qmap.h:2 src/corelib/tools/qset.h:1 The lesser-evil is to bump Q_COMPILER_INITIALIZER_LISTS to version GCC 4.5 and retain usage of required (by standard) initializer_list typedefs. Change-Id: I38d6fa0ef3dc7d958587b406d33e3e3a7378c026 Reviewed-by: Thiago Macieira --- src/corelib/global/qcompilerdetection.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 3bf1cc0cbb..2c7a00133d 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -742,7 +742,6 @@ # define Q_COMPILER_DEFAULT_MEMBERS # define Q_COMPILER_DELETE_MEMBERS # define Q_COMPILER_EXTERN_TEMPLATES -# define Q_COMPILER_INITIALIZER_LISTS # define Q_COMPILER_UNIFORM_INIT # define Q_COMPILER_UNICODE_STRINGS # define Q_COMPILER_VARIADIC_TEMPLATES @@ -750,6 +749,9 @@ # if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 /* C++11 features supported in GCC 4.5: */ # define Q_COMPILER_EXPLICIT_CONVERSIONS + /* GCC 4.4 implements initializer_list but does not define typedefs required + * by the standard. */ +# define Q_COMPILER_INITIALIZER_LISTS # define Q_COMPILER_LAMBDA # define Q_COMPILER_RAW_STRINGS # endif From 289e9af668df8b9f869ee42e295b582f246d6e32 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Sat, 6 Sep 2014 19:29:41 +0200 Subject: [PATCH 78/89] Define EGL_EGLEXT_PROTOTYPES for ANGLE Otherwise the protos are not pulled in so the ANGLE-only build cannot suceed (unless the flag is defined from somewhere else). Task-number: QTBUG-41164 Change-Id: I959d154da88f7ccc8159ec7e810ffdba0e7f50ea Reviewed-by: Andrew Knight --- src/plugins/platforms/windows/qwindowseglcontext.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index e27b55da3e..8892fa6daa 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -47,6 +47,7 @@ #include #if defined(QT_OPENGL_ES_2_ANGLE) || defined(QT_OPENGL_DYNAMIC) +# define EGL_EGLEXT_PROTOTYPES # include #endif From f3cee50216b066dc204ab4482d329f4ff988b1e2 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Fri, 5 Sep 2014 16:24:23 +0400 Subject: [PATCH 79/89] Fix a conversion of coordinates of a TouchBegin event To convert coordinates to a parent's coordinate system one should translate them by an offset of a child widget relative to it's parent widget. QRect::moveCenter() doesn't translate, it sets the coordinates of the touch point's center to this offset. Change-Id: I9d823784803bd1448c0d665944090674d3ff518b Reviewed-by: Laszlo Agocs Reviewed-by: Shawn Rutledge --- src/widgets/kernel/qapplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index f438f60e47..3486396f54 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -3563,7 +3563,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) for (int i = 0; i < touchEvent->_touchPoints.size(); ++i) { QTouchEvent::TouchPoint &pt = touchEvent->_touchPoints[i]; QRectF rect = pt.rect(); - rect.moveCenter(offset); + rect.translate(offset); pt.d->rect = rect; pt.d->startPos = pt.startPos() + offset; pt.d->lastPos = pt.lastPos() + offset; From 267eb25151ce8d1d4d9abf04b9204afa9977b723 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 8 Sep 2014 11:46:21 +0200 Subject: [PATCH 80/89] Enhance the VAO docs Make it clear that the class is usable regardless of the OpenGL version the app is targeting. It may just do nothing. Change-Id: I50e68a46e36ef1f4694016311af93c6f8719ce4f Reviewed-by: Sean Harmer --- src/gui/opengl/qopenglvertexarrayobject.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/gui/opengl/qopenglvertexarrayobject.cpp b/src/gui/opengl/qopenglvertexarrayobject.cpp index 3b106fecf5..c24254756b 100644 --- a/src/gui/opengl/qopenglvertexarrayobject.cpp +++ b/src/gui/opengl/qopenglvertexarrayobject.cpp @@ -386,6 +386,16 @@ QOpenGLVertexArrayObject::~QOpenGLVertexArrayObject() that supports vertex array objects current for this function to succeed. Returns \c true if the OpenGL vertex array object was successfully created. + + When the return value is \c false, vertex array object support is not available. This + is not an error: on systems with OpenGL 2.x or OpenGL ES 2.0 vertex array objects may + not be supported. The application is free to continue execution in this case, but it + then has to be prepared to operate in a VAO-less manner too. This means that instead + of merely calling bind(), the value of isCreated() must be checked and the vertex + arrays has to be initialized in the traditional way when there is no vertex array + object present. + + \sa isCreated() */ bool QOpenGLVertexArrayObject::create() { From df5db1dfb2409c1bd83dbb108a8eec5a00712176 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 8 Sep 2014 15:32:04 +0200 Subject: [PATCH 81/89] Fix linking of tst_qwindow with dynamic Open GL. Task-number: QTBUG-40696 Change-Id: If80a5e9b96e2eb7e50e02eefbe6e54d0b028c144 Reviewed-by: Laszlo Agocs --- tests/auto/gui/kernel/qwindow/qwindow.pro | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/gui/kernel/qwindow/qwindow.pro b/tests/auto/gui/kernel/qwindow/qwindow.pro index e419a10440..5210585796 100644 --- a/tests/auto/gui/kernel/qwindow/qwindow.pro +++ b/tests/auto/gui/kernel/qwindow/qwindow.pro @@ -4,3 +4,5 @@ TARGET = tst_qwindow QT += core-private gui-private testlib SOURCES += tst_qwindow.cpp + +contains(QT_CONFIG,dynamicgl):win32:!wince*:!winrt: LIBS += -luser32 From 935186d76e055083eda75b91488c9affec1fd110 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 8 Sep 2014 10:10:07 +0200 Subject: [PATCH 82/89] Improve QOpenGLWidget docs regarding fb preservation QOpenGLWindow already has some notes regarding this. It must be mentioned in QOpenGLWidget too. Change-Id: I0af90c9410a1c44cb9dd9ce58aa0371a58c57f65 Reviewed-by: Paul Olav Tvete --- src/widgets/kernel/qopenglwidget.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index d8f31bfcc8..757cac8cea 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -228,6 +228,22 @@ QT_BEGIN_NAMESPACE regarding stacking orders for example. QOpenGLWidget avoids this by not creating a separate native window. + Due to being backed by a framebuffer object, the behavior of QOpenGLWidget is + very similar to QOpenGLWindow with the update behavior set to \c + PartialUpdateBlit or \c PartialUpdateBlend. This means that the contents are + preserved between paintGL() calls so that incremental rendering is + possible. With QGLWidget (and naturally QOpenGLWindow with the default update + behavior) this is usually not the case because swapping the buffers leaves the + back buffer with undefined contents. + + \note Most applications do not need incremental rendering because they will + render everything in the view on every paint call. In this case it is + important to call glClear() as early as possible in paintGL(). This helps + mobile GPUs that use a tile-based architecture to recognize that the tile + buffer does not need to be reloaded with the framebuffer's previous + contents. Omitting the clear call can lead to significant performance drops on + such systems. + \section1 Multisampling To enable multisampling, set the number of requested samples on the @@ -372,7 +388,7 @@ QT_BEGIN_NAMESPACE \e{OpenGL is a trademark of Silicon Graphics, Inc. in the United States and other countries.} - \sa QOpenGLFunctions + \sa QOpenGLFunctions, QOpenGLWindow */ /*! From af155105a9f48e3e96a7f1961732c38ff12465f4 Mon Sep 17 00:00:00 2001 From: Adam Strzelecki Date: Wed, 6 Aug 2014 18:53:05 +0200 Subject: [PATCH 83/89] qmake: Add QMAKE_SONAME_PREFIX variable If defined, the value of this variable is prepended to the built shared library's SONAME identifier. For more information, see: qmake/doc/src/qmake-manual.qdoc#qmake-soname-prefix Task-number: QTBUG-31814 Change-Id: I4bceaf0c93162e4fad6bb424af1b82e74d38acdc Reviewed-by: Jake Petroules --- .../snippets/code/doc_src_qmake-manual.pro | 12 +++++++ qmake/doc/src/qmake-manual.qdoc | 33 +++++++++++++++++++ qmake/generators/unix/unixmake2.cpp | 7 ++++ 3 files changed, 52 insertions(+) diff --git a/qmake/doc/snippets/code/doc_src_qmake-manual.pro b/qmake/doc/snippets/code/doc_src_qmake-manual.pro index 07bed62763..1bd89d2f04 100644 --- a/qmake/doc/snippets/code/doc_src_qmake-manual.pro +++ b/qmake/doc/snippets/code/doc_src_qmake-manual.pro @@ -970,3 +970,15 @@ int main() { return featureFunction(); } # /project.pro qtCompileTest(test) #! [182] + +#! [183] +# /project.pro +QMAKE_SONAME_PREFIX = @rpath +#! [183] + +#! [184] +# /project.pro +QMAKE_SONAME_PREFIX = @executable_path/../Frameworks +QMAKE_SONAME_PREFIX = @loader_path/Frameworks +QMAKE_SONAME_PREFIX = /Library/Frameworks +#! [184] diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index ad08f729a7..52fc1ec4fb 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -2071,6 +2071,39 @@ qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. + \section1 QMAKE_SONAME_PREFIX + + If defined, the value of this variable is used as a path to be prepended to + the built shared library's \c SONAME identifier. The \c SONAME is the + identifier that the dynamic linker will later use to reference the library. + In general this reference may be a library name or full library path. On OS + X and iOS, the path may be specified relatively using the following + placeholders: + + \table + \header \li Placeholder \li Effect + \row \li @rpath + \li Expands to paths defined by LC_RPATH mach-o commands in + the current process executable or the referring libraries. + \row \li @executable_path + \li Expands to the current process executable location. + \row \li @loader_path + \li Expands to the referring executable or library location. + \endtable + + In most cases, using \c @rpath is sufficient and recommended: + + \snippet code/doc_src_qmake-manual.pro 183 + + However, the prefix may be also specified using different placeholders, or + an absolute path, such as one of the following: + + \snippet code/doc_src_qmake-manual.pro 184 + + For more information, see + \l{https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/dyld.1.html}{dyld} + documentation on dynamic library install names. + \section1 QMAKE_TARGET Specifies the name of the project target. The value of this diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index e16e0f5c20..c68cebfd8c 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -1265,6 +1265,13 @@ void UnixMakefileGenerator::init2() if(!instpath.endsWith(Option::dir_sep)) instpath += Option::dir_sep; soname.prepend(instpath); + } else if (!project->isEmpty("QMAKE_SONAME_PREFIX")) { + QString sonameprefix = project->first("QMAKE_SONAME_PREFIX").toQString(); + if (!sonameprefix.startsWith('@') && !sonameprefix.startsWith('$')) + sonameprefix = Option::fixPathToTargetOS(sonameprefix, false); + if (!sonameprefix.endsWith(Option::dir_sep)) + sonameprefix += Option::dir_sep; + soname.prepend(sonameprefix); } project->values("QMAKE_LFLAGS_SONAME").first() += escapeFilePath(soname); } From fefa4dc1f0a2784b2377e7d0b64f754698f7c59c Mon Sep 17 00:00:00 2001 From: Maks Naumov Date: Sat, 6 Sep 2014 14:33:28 +0300 Subject: [PATCH 84/89] Windows styles: Avoid theme.rect recalculation In both cases theme.rect calculated right after the "sub & SC_ScrollBarSlider" test. Change-Id: I9fa0c4e1327e68b4184674a13e7a4bf362f8deff Reviewed-by: Adam Majer Reviewed-by: Friedemann Kleint --- src/widgets/styles/qwindowsvistastyle.cpp | 1 - src/widgets/styles/qwindowsxpstyle.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index e5acd22f16..8b79a68f61 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -1757,7 +1757,6 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle stateId = SCRBS_NORMAL; // Draw handle - theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); theme.partId = flags & State_Horizontal ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT; theme.stateId = stateId; d->drawBackground(theme); diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index 08ebe1c5ad..8dc3c6cb48 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -2758,7 +2758,6 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo stateId = SCRBS_NORMAL; // Draw handle - theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); theme.partId = flags & State_Horizontal ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT; theme.stateId = stateId; d->drawBackground(theme); From e5dbef74b4fbd7943ca175ce6d0088f1d79c928f Mon Sep 17 00:00:00 2001 From: Maks Naumov Date: Sat, 6 Sep 2014 19:18:28 +0300 Subject: [PATCH 85/89] QRegion: remove check for null ptr after "new" operator Change-Id: Iebba0b1f024e22cd36a04c53377b3958638b389e Reviewed-by: Marc Mutz Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Laszlo Agocs --- src/gui/painting/qregion.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp index eb197378ad..549dce2923 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -3521,8 +3521,7 @@ static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule) POINTBLOCK *tmpPtBlock; int numFullPtBlocks = 0; - if (!(region = new QRegionPrivate)) - return 0; + region = new QRegionPrivate; /* special case a rectangle */ if (((Count == 4) || From 5042145dd97e425710194f064ed0796d91a0d259 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Sat, 6 Sep 2014 17:20:54 +0200 Subject: [PATCH 86/89] Fix typo in QMetaType documentation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I934b68978fb32a518ed7cf9b47f1600982f58f66 Reviewed-by: Jędrzej Nowacki --- src/corelib/kernel/qmetatype.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 0647513221..5fe1047426 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -310,7 +310,7 @@ struct DefinedTypesFilter { name to a type so that it can be created and destructed dynamically at run-time. Declare new types with Q_DECLARE_METATYPE() to make them available to QVariant and other template-based functions. - Call qRegisterMetaType() to make type available to non-template based + Call qRegisterMetaType() to make types available to non-template based functions, such as the queued signal and slot connections. Any class or struct that has a public default From 8db7e476995cfd567e126c3254c68d010e758d79 Mon Sep 17 00:00:00 2001 From: Maks Naumov Date: Sat, 6 Sep 2014 17:43:30 +0300 Subject: [PATCH 87/89] QNetworkReply: move "State" enum declaration into QNetworkReplyPrivate Change-Id: If63a029a7a7ef84fc1b4b73f5bab495992ea7e02 Reviewed-by: Peter Hartmann --- src/network/access/qnetworkreply_p.h | 10 +++++++ src/network/access/qnetworkreplyhttpimpl.cpp | 22 +++++++-------- src/network/access/qnetworkreplyhttpimpl_p.h | 10 ------- src/network/access/qnetworkreplyimpl.cpp | 28 ++++++++++---------- src/network/access/qnetworkreplyimpl_p.h | 10 ------- 5 files changed, 35 insertions(+), 45 deletions(-) diff --git a/src/network/access/qnetworkreply_p.h b/src/network/access/qnetworkreply_p.h index ad11ef3964..55d3d85592 100644 --- a/src/network/access/qnetworkreply_p.h +++ b/src/network/access/qnetworkreply_p.h @@ -65,6 +65,16 @@ QT_BEGIN_NAMESPACE class QNetworkReplyPrivate: public QIODevicePrivate, public QNetworkHeadersPrivate { public: + enum State { + Idle, // The reply is idle. + Buffering, // The reply is buffering outgoing data. + Working, // The reply is uploading/downloading data. + Finished, // The reply has finished. + Aborted, // The reply has been aborted. + WaitingForSession, // The reply is waiting for the session to open before connecting. + Reconnecting // The reply will reconnect to once roaming has completed. + }; + QNetworkReplyPrivate(); QNetworkRequest request; QUrl url; diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index c5cf849a55..920dfdbb38 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -250,8 +250,8 @@ void QNetworkReplyHttpImpl::close() { Q_D(QNetworkReplyHttpImpl); - if (d->state == QNetworkReplyHttpImplPrivate::Aborted || - d->state == QNetworkReplyHttpImplPrivate::Finished) + if (d->state == QNetworkReplyPrivate::Aborted || + d->state == QNetworkReplyPrivate::Finished) return; // According to the documentation close only stops the download @@ -268,23 +268,23 @@ void QNetworkReplyHttpImpl::abort() { Q_D(QNetworkReplyHttpImpl); // FIXME - if (d->state == QNetworkReplyHttpImplPrivate::Finished || d->state == QNetworkReplyHttpImplPrivate::Aborted) + if (d->state == QNetworkReplyPrivate::Finished || d->state == QNetworkReplyPrivate::Aborted) return; QNetworkReply::close(); - if (d->state != QNetworkReplyHttpImplPrivate::Finished) { + if (d->state != QNetworkReplyPrivate::Finished) { // call finished which will emit signals // FIXME shouldn't this be emitted Queued? d->error(OperationCanceledError, tr("Operation canceled")); // If state is WaitingForSession, calling finished has no effect - if (d->state == QNetworkReplyHttpImplPrivate::WaitingForSession) - d->state = QNetworkReplyHttpImplPrivate::Working; + if (d->state == QNetworkReplyPrivate::WaitingForSession) + d->state = QNetworkReplyPrivate::Working; d->finished(); } - d->state = QNetworkReplyHttpImplPrivate::Aborted; + d->state = QNetworkReplyPrivate::Aborted; emit abortHttpRequest(); } @@ -1800,13 +1800,13 @@ void QNetworkReplyHttpImplPrivate::_q_networkSessionConnected() return; switch (state) { - case QNetworkReplyImplPrivate::Buffering: - case QNetworkReplyImplPrivate::Working: - case QNetworkReplyImplPrivate::Reconnecting: + case QNetworkReplyPrivate::Buffering: + case QNetworkReplyPrivate::Working: + case QNetworkReplyPrivate::Reconnecting: // Migrate existing downloads to new network connection. migrateBackend(); break; - case QNetworkReplyImplPrivate::WaitingForSession: + case QNetworkReplyPrivate::WaitingForSession: // Start waiting requests. QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); break; diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h index 06a5383ae4..b7de947a29 100644 --- a/src/network/access/qnetworkreplyhttpimpl_p.h +++ b/src/network/access/qnetworkreplyhttpimpl_p.h @@ -160,16 +160,6 @@ public: static QHttpNetworkRequest::Priority convert(const QNetworkRequest::Priority& prio); - enum State { - Idle, // The reply is idle. - Buffering, // The reply is buffering outgoing data. - Working, // The reply is uploading/downloading data. - Finished, // The reply has finished. - Aborted, // The reply has been aborted. - WaitingForSession, // The reply is waiting for the session to open before connecting. - Reconnecting // The reply will reconnect to once roaming has completed. - }; - QNetworkReplyHttpImplPrivate(); ~QNetworkReplyHttpImplPrivate(); diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 616019ea41..be0ddf1388 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -301,13 +301,13 @@ void QNetworkReplyImplPrivate::_q_networkSessionConnected() return; switch (state) { - case QNetworkReplyImplPrivate::Buffering: - case QNetworkReplyImplPrivate::Working: - case QNetworkReplyImplPrivate::Reconnecting: + case QNetworkReplyPrivate::Buffering: + case QNetworkReplyPrivate::Working: + case QNetworkReplyPrivate::Reconnecting: // Migrate existing downloads to new network connection. migrateBackend(); break; - case QNetworkReplyImplPrivate::WaitingForSession: + case QNetworkReplyPrivate::WaitingForSession: // Start waiting requests. QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); break; @@ -916,7 +916,7 @@ QNetworkReplyImpl::~QNetworkReplyImpl() void QNetworkReplyImpl::abort() { Q_D(QNetworkReplyImpl); - if (d->state == QNetworkReplyImplPrivate::Finished || d->state == QNetworkReplyImplPrivate::Aborted) + if (d->state == QNetworkReplyPrivate::Finished || d->state == QNetworkReplyPrivate::Aborted) return; // stop both upload and download @@ -927,14 +927,14 @@ void QNetworkReplyImpl::abort() QNetworkReply::close(); - if (d->state != QNetworkReplyImplPrivate::Finished) { + if (d->state != QNetworkReplyPrivate::Finished) { // call finished which will emit signals d->error(OperationCanceledError, tr("Operation canceled")); - if (d->state == QNetworkReplyImplPrivate::WaitingForSession) - d->state = QNetworkReplyImplPrivate::Working; + if (d->state == QNetworkReplyPrivate::WaitingForSession) + d->state = QNetworkReplyPrivate::Working; d->finished(); } - d->state = QNetworkReplyImplPrivate::Aborted; + d->state = QNetworkReplyPrivate::Aborted; // finished may access the backend if (d->backend) { @@ -946,8 +946,8 @@ void QNetworkReplyImpl::abort() void QNetworkReplyImpl::close() { Q_D(QNetworkReplyImpl); - if (d->state == QNetworkReplyImplPrivate::Aborted || - d->state == QNetworkReplyImplPrivate::Finished) + if (d->state == QNetworkReplyPrivate::Aborted || + d->state == QNetworkReplyPrivate::Finished) return; // stop the download @@ -1041,7 +1041,7 @@ qint64 QNetworkReplyImpl::readData(char *data, qint64 maxlen) if (d->downloadBuffer) { qint64 maxAvail = qMin(d->downloadBufferCurrentSize - d->downloadBufferReadPosition, maxlen); if (maxAvail == 0) - return d->state == QNetworkReplyImplPrivate::Finished ? -1 : 0; + return d->state == QNetworkReplyPrivate::Finished ? -1 : 0; // FIXME what about "Aborted" state? memcpy(data, d->downloadBuffer + d->downloadBufferReadPosition, maxAvail); d->downloadBufferReadPosition += maxAvail; @@ -1050,7 +1050,7 @@ qint64 QNetworkReplyImpl::readData(char *data, qint64 maxlen) if (d->readBuffer.isEmpty()) - return d->state == QNetworkReplyImplPrivate::Finished ? -1 : 0; + return d->state == QNetworkReplyPrivate::Finished ? -1 : 0; // FIXME what about "Aborted" state? d->backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite); @@ -1101,7 +1101,7 @@ bool QNetworkReplyImplPrivate::migrateBackend() if (!backend->canResume()) return false; - state = QNetworkReplyImplPrivate::Reconnecting; + state = QNetworkReplyPrivate::Reconnecting; if (backend) { delete backend; diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index 9edc0f6b59..3340dcc91e 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -118,16 +118,6 @@ public: NotifyCopyFinished }; - enum State { - Idle, // The reply is idle. - Buffering, // The reply is buffering outgoing data. - Working, // The reply is uploading/downloading data. - Finished, // The reply has finished. - Aborted, // The reply has been aborted. - WaitingForSession, // The reply is waiting for the session to open before connecting. - Reconnecting // The reply will reconnect to once roaming has completed. - }; - typedef QQueue NotificationQueue; QNetworkReplyImplPrivate(); From 3203239bd80937c0821602f8ccfca952f7c0692c Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Wed, 3 Sep 2014 15:58:11 +0400 Subject: [PATCH 88/89] xcb: fix getting a XdndAware property if a proxy window exists According to the XDND standard (http://www.newplanetsoftware.com/xdnd/) if the proxy window exists then it should be checked for the XdndAware property rather than the target window directly. c3f9de62966d32d8e33d62eb374fe2657a4cfebe introduced the mistake. In the old code the proxy window was used. Change-Id: I83b66d4b1f08a1f44d5c1451d0f1735c084bcf09 Spotted-by: Alexander Smirnov Reviewed-by: Lars Knoll --- src/plugins/platforms/xcb/qxcbdrag.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index fa5ccf58ef..e3fae73fd3 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -406,7 +406,7 @@ void QXcbDrag::move(const QMouseEvent *me) int target_version = 1; if (proxy_target) { - xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, target, + xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, proxy_target, atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 1); xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0); if (!reply || reply->type == XCB_NONE) From 71df09b6cca7cd7a673bf39f49d0dda28b78a860 Mon Sep 17 00:00:00 2001 From: Dyami Caliri Date: Tue, 9 Sep 2014 12:07:09 -0700 Subject: [PATCH 89/89] Fix garbled resize with QOpenGLWidget when using multi-sampling. If you configure QOpenGLWidget to use sampling, the 'resolvedFbo' isn't updated during resizing. This leads to garbled views. Change-Id: I9f9265520134bcf12436778773507df936c5fbb6 Reviewed-by: Laszlo Agocs --- src/widgets/kernel/qopenglwidget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index 757cac8cea..3dae22cdc7 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -896,6 +896,7 @@ void QOpenGLWidget::resizeEvent(QResizeEvent *e) resizeGL(width(), height()); d->invokeUserPaint(); d->context->functions()->glFlush(); + d->resolveSamples(); } /*!