summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOswald Buddenhagen <[email protected]>2014-09-10 11:41:29 +0200
committerOswald Buddenhagen <[email protected]>2014-09-10 11:42:50 +0200
commitd572ab1bb446e880fcb8d27294ba8149550f1659 (patch)
treed29c449b551e47569c6d9f146ba9e86810c05353
parent211cef46f6d9d8738c09f906f9c0c3080b445dc8 (diff)
parent71df09b6cca7cd7a673bf39f49d0dda28b78a860 (diff)
Merge remote-tracking branch 'origin/5.4' into dev
-rwxr-xr-xconfigure2
-rw-r--r--doc/global/externalsites.qdocconf3
-rw-r--r--doc/global/fileextensions.qdocconf2
-rw-r--r--doc/global/template/style/offline.css16
-rw-r--r--doc/global/template/style/online.css16
-rw-r--r--examples/opengl/hellowindow/hellowindow.cpp27
-rw-r--r--qmake/doc/snippets/code/doc_src_qmake-manual.pro12
-rw-r--r--qmake/doc/src/qmake-manual.qdoc33
-rw-r--r--qmake/generators/unix/unixmake2.cpp7
-rw-r--r--src/3rdparty/angle/src/common/platform.h2
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Context.cpp4
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp4
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp4
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp8
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h2
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp27
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h2
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp60
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java21
-rw-r--r--src/angle/angle.pro3
-rw-r--r--src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch203
-rw-r--r--src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch175
-rw-r--r--src/angle/src/config.pri4
-rw-r--r--src/angle/src/libEGL/libEGL.pro5
-rw-r--r--src/angle/src/libGLESv2/libGLESv2.pro4
-rw-r--r--src/corelib/global/archdetect.cpp6
-rw-r--r--src/corelib/global/qcompilerdetection.h4
-rw-r--r--src/corelib/kernel/qmetatype.cpp2
-rw-r--r--src/corelib/kernel/qtcore_eval.cpp6
-rw-r--r--src/corelib/tools/qdatetimeparser.cpp2
-rw-r--r--src/corelib/tools/qelapsedtimer.cpp15
-rw-r--r--src/corelib/tools/qelapsedtimer.h7
-rw-r--r--src/corelib/tools/qelapsedtimer_generic.cpp2
-rw-r--r--src/corelib/tools/qrect.cpp2
-rw-r--r--src/gui/accessible/qaccessible.cpp96
-rw-r--r--src/gui/image/qiconloader.cpp9
-rw-r--r--src/gui/image/qimage.cpp2
-rw-r--r--src/gui/image/qimage.h2
-rw-r--r--src/gui/kernel/qopenglwindow.h6
-rw-r--r--src/gui/opengl/qopengl.h6
-rw-r--r--src/gui/opengl/qopenglfunctions.h2
-rw-r--r--src/gui/opengl/qopenglgradientcache.cpp2
-rw-r--r--src/gui/opengl/qopenglvertexarrayobject.cpp10
-rw-r--r--src/gui/painting/qregion.cpp3
-rw-r--r--src/gui/text/qfontengine_ft.cpp25
-rw-r--r--src/gui/text/qfontengine_ft_p.h3
-rw-r--r--src/gui/text/qtextengine.cpp3
-rw-r--r--src/network/access/qnetworkreply_p.h10
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp22
-rw-r--r--src/network/access/qnetworkreplyhttpimpl_p.h10
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp28
-rw-r--r--src/network/access/qnetworkreplyimpl_p.h10
-rw-r--r--src/network/socket/qnativesocketengine_winrt.cpp9
-rw-r--r--src/network/ssl/qasn1element.cpp55
-rw-r--r--src/network/ssl/qasn1element_p.h20
-rw-r--r--src/network/ssl/qsslcertificate.cpp150
-rw-r--r--src/network/ssl/qsslcertificate_p.h5
-rw-r--r--src/network/ssl/qsslcertificate_qt.cpp256
-rw-r--r--src/network/ssl/qsslkey_openssl.cpp3
-rw-r--r--src/network/ssl/qsslkey_p.cpp52
-rw-r--r--src/network/ssl/qsslkey_p.h13
-rw-r--r--src/network/ssl/qsslkey_qt.cpp82
-rw-r--r--src/network/ssl/qsslkey_winrt.cpp98
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext.cpp11
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcursor.cpp3
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcursor_p.h5
-rw-r--r--src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp3
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp6
-rw-r--r--src/plugins/platforms/android/qandroideventdispatcher.cpp21
-rw-r--r--src/plugins/platforms/android/qandroideventdispatcher.h3
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.cpp10
-rw-r--r--src/plugins/platforms/android/qandroidplatformopenglwindow.cpp4
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp16
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp10
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h4
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp17
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h9
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp8
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h3
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp154
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h6
-rw-r--r--src/plugins/platforms/directfb/qdirectfbblitter.cpp71
-rw-r--r--src/plugins/platforms/directfb/qdirectfbblitter.h3
-rw-r--r--src/plugins/platforms/eglfs/eglfs.pri5
-rw-r--r--src/plugins/platforms/eglfs/qeglfshooks_kms.cpp422
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.cpp9
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm4
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm49
-rw-r--r--src/plugins/platforms/ios/qioswindow.h1
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm6
-rw-r--r--src/plugins/platforms/ios/quiview_textinput.mm21
-rw-r--r--src/plugins/platforms/kms/qkmsscreen.cpp9
-rw-r--r--src/plugins/platforms/kms/qkmsscreen.h3
-rw-r--r--src/plugins/platforms/platforms.pro2
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.cpp41
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.h1
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp46
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h8
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp20
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h5
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp8
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp10
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp2
-rw-r--r--src/src.pro1
-rw-r--r--src/tools/qdoc/htmlgenerator.cpp90
-rw-r--r--src/widgets/accessible/qaccessiblemenu.cpp3
-rw-r--r--src/widgets/accessible/qaccessiblewidgets.cpp3
-rw-r--r--src/widgets/accessible/simplewidgets.cpp21
-rw-r--r--src/widgets/graphicsview/qgraphicsitem_p.h2
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.cpp4
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.h1
-rw-r--r--src/widgets/graphicsview/qgraphicsscenelinearindex_p.h52
-rw-r--r--src/widgets/kernel/qapplication.cpp2
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp19
-rw-r--r--src/widgets/kernel/qopenglwidget.h6
-rw-r--r--src/widgets/kernel/qstandardgestures.cpp2
-rw-r--r--src/widgets/kernel/qwidget.cpp20
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp5
-rw-r--r--src/widgets/styles/qcommonstyle.cpp110
-rw-r--r--src/widgets/styles/qwindowsstyle.cpp245
-rw-r--r--src/widgets/styles/qwindowsstyle_p_p.h11
-rw-r--r--src/widgets/styles/qwindowsvistastyle.cpp267
-rw-r--r--src/widgets/styles/qwindowsvistastyle_p_p.h2
-rw-r--r--src/widgets/styles/qwindowsxpstyle.cpp422
-rw-r--r--src/widgets/styles/qwindowsxpstyle_p_p.h129
-rw-r--r--src/widgets/util/qscroller.cpp5
-rw-r--r--src/widgets/widgets/qabstractscrollarea.cpp2
-rw-r--r--src/widgets/widgets/qlineedit.cpp4
-rw-r--r--src/widgets/widgets/qlineedit_p.cpp2
-rw-r--r--src/widgets/widgets/qmdisubwindow.cpp3
-rw-r--r--src/widgets/widgets/qplaintextedit.cpp3
-rw-r--r--tests/auto/corelib/global/qglobal/tst_qglobal.cpp13
-rw-r--r--tests/auto/corelib/tools/qelapsedtimer/tst_qelapsedtimer.cpp10
-rw-r--r--tests/auto/gui/kernel/qwindow/qwindow.pro2
-rw-r--r--tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp68
-rw-r--r--tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp66
-rw-r--r--tests/auto/network/ssl/qsslkey/qsslkey.pro3
-rw-r--r--tests/auto/network/ssl/qsslkey/rsa-with-passphrase-rc2.pem18
-rw-r--r--tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp126
-rw-r--r--tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp25
-rw-r--r--tests/auto/other/other.pro3
-rw-r--r--tests/auto/other/qaccessibility/accessiblewidgets.h167
-rw-r--r--tests/auto/other/qaccessibility/qaccessibility.pro3
-rw-r--r--tests/auto/other/qaccessibility/tst_qaccessibility.cpp141
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp17
-rw-r--r--tools/configure/configureapp.cpp15
150 files changed, 3587 insertions, 1262 deletions
diff --git a/configure b/configure
index 7cbd11d98df..0c65aac14aa 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,"
diff --git a/doc/global/externalsites.qdocconf b/doc/global/externalsites.qdocconf
new file mode 100644
index 00000000000..46ce8401c0c
--- /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 ec47dc9c7f7..0a106d5befe 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
diff --git a/doc/global/template/style/offline.css b/doc/global/template/style/offline.css
index 7fc0d62fa61..5957e3840d0 100644
--- a/doc/global/template/style/offline.css
+++ b/doc/global/template/style/offline.css
@@ -97,6 +97,10 @@ a[href*="https://"], 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 0dc01d396b9..5d0cd7ecfb8 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/examples/opengl/hellowindow/hellowindow.cpp b/examples/opengl/hellowindow/hellowindow.cpp
index da31fee9209..57eb111edbf 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()
diff --git a/qmake/doc/snippets/code/doc_src_qmake-manual.pro b/qmake/doc/snippets/code/doc_src_qmake-manual.pro
index 07bed627633..1bd89d2f042 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 root>/project.pro
qtCompileTest(test)
#! [182]
+
+#! [183]
+# <project root>/project.pro
+QMAKE_SONAME_PREFIX = @rpath
+#! [183]
+
+#! [184]
+# <project root>/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 ad08f729a7d..52fc1ec4fb8 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 e16e0f5c20f..c68cebfd8cc 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);
}
diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
index cedc6f2f222..44c5c7c03bc 100644
--- a/src/3rdparty/angle/src/common/platform.h
+++ b/src/3rdparty/angle/src/common/platform.h
@@ -59,8 +59,10 @@
# include <d3d10.h>
# include <d3d11.h>
# include <dxgi.h>
+# if _MSC_VER >= 1700
# include <dxgi1_2.h>
# include <d3dcompiler.h>
+# endif
# endif
# undef near
diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp
index 8201acda101..99df85b0d35 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<GLuint>(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<GLuint>(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 352da9654a7..1301124b2dd 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/Clear11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
index 8db5ea27c17..5121950da03 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/Query11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp
index 17cf5cad47a..e5e00325b2c 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 ba9f76e5dec..82182957afb 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 651b065ca2d..3ba0cc767ba 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 a31f15ee649..b54f75d859b 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<DXGI_FORMAT, MultisampleSupportInfo> MultisampleSupportMap;
+ typedef std::unordered_map<GLenum, MultisampleSupportInfo> 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 d3d135fe5be..d914a8201b7 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,40 @@
#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
+#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
{
@@ -273,7 +307,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 +327,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 +349,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 +371,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 +391,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 +416,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 +436,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 +457,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 +477,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 +497,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 +517,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 +537,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:
@@ -622,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/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
index b4b483b416d..c85104b11e8 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<Integer, QtSurface> 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;
}
@@ -1085,11 +1095,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/angle/angle.pro b/src/angle/angle.pro
index 78b53dfa14c..c454fee8f97 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 <GLES2/gl2.h>"
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/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 00000000000..dcff4a323e9
--- /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 <[email protected]>
+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 <d3d10.h>
+ # include <d3d11.h>
+ # include <dxgi.h>
++# if _MSC_VER >= 1700
+ # include <dxgi1_2.h>
+ # include <d3dcompiler.h>
++# 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/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 00000000000..3cf6c67d16e
--- /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 <[email protected]>
+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<GLuint>(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<GLuint>(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<DXGI_FORMAT, MultisampleSupportInfo> MultisampleSupportMap;
++ typedef std::unordered_map<GLenum, MultisampleSupportInfo> 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
+
diff --git a/src/angle/src/config.pri b/src/angle/src/config.pri
index ccc4cb16a1d..07a18620da6 100644
--- a/src/angle/src/config.pri
+++ b/src/angle/src/config.pri
@@ -37,7 +37,9 @@ DEFINES += _WINDOWS \
NOMINMAX \
WIN32_LEAN_AND_MEAN=1
-!winrt: DEFINES += ANGLE_ENABLE_D3D9
+!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
diff --git a/src/angle/src/libEGL/libEGL.pro b/src/angle/src/libEGL/libEGL.pro
index dc286ca11dd..48ce7055fd8 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 8109c349423..2e84df0d392 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
diff --git a/src/corelib/global/archdetect.cpp b/src/corelib/global/archdetect.cpp
index e35595e7278..344c3630319 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/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 3bf1cc0cbbb..2c7a00133df 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
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 06475132218..5fe1047426f 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
diff --git a/src/corelib/kernel/qtcore_eval.cpp b/src/corelib/kernel/qtcore_eval.cpp
index a5c4c366389..c938e0fb5be 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<const char*>(qt_eval_expiry_date + 12);
+
QDate today = QDate::currentDate();
- QDate build = QLibraryInfo::buildDate();
- return qMax<qint64>(-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()
diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp
index fb5c5f5943a..edb4f4e048e 100644
--- a/src/corelib/tools/qdatetimeparser.cpp
+++ b/src/corelib/tools/qdatetimeparser.cpp
@@ -749,7 +749,6 @@ int QDateTimeParser::parseSection(const QDateTime &currentValue, 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 &currentValue, int sectionInde
if (num != -1) {
state = (used == sectiontext.size() ? Acceptable : Intermediate);
- QString str = text;
text.replace(index, used, sectiontext.left(used));
} else {
state = Intermediate;
diff --git a/src/corelib/tools/qelapsedtimer.cpp b/src/corelib/tools/qelapsedtimer.cpp
index 1da85fce96c..08fc1cf5e2b 100644
--- a/src/corelib/tools/qelapsedtimer.cpp
+++ b/src/corelib/tools/qelapsedtimer.cpp
@@ -202,6 +202,17 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \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
Returns \c true if this object and \a other contain the same time.
@@ -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 b06afe4ab4c..7df5dec63ad 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 6324be00c03..7a52faa3c57 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/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp
index 04269e485b1..57cc863696e 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()).
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index f9fbc92d208..b3d78435061 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -1897,16 +1897,65 @@ QDebug operator<<(QDebug d, const QAccessibleEvent &ev)
*/
/*!
+ \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();
@@ -1922,7 +1971,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();
}
@@ -1954,12 +2007,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();
@@ -1975,7 +2042,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();
}
@@ -2018,12 +2089,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();
@@ -2042,8 +2127,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/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index 12d9f9f14d3..5a4460dea38 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();
}
@@ -561,15 +561,16 @@ void QIconLoaderEngine::virtual_hook(int id, void *data)
{
QIconEngine::AvailableSizesArgument &arg
= *reinterpret_cast<QIconEngine::AvailableSizesArgument*>(data);
- arg.sizes.clear();
const int N = m_entries.size();
- arg.sizes.reserve(N);
+ QList<QSize> 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:
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index c3b4b1444a3..5de686c1ea6 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1368,7 +1368,7 @@ void QImage::setColorTable(const QVector<QRgb> colors)
if (!d)
return;
- d->colortable = colors;
+ d->colortable = qMove(const_cast<QVector<QRgb>&>(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 844bbb2eba9..3e73462efca 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<QRgb> colorTable() const;
- void setColorTable(const QVector<QRgb> colors);
+ void setColorTable(const QVector<QRgb> colors); // ### Qt 6: remove const
qreal devicePixelRatio() const;
void setDevicePixelRatio(qreal scaleFactor);
diff --git a/src/gui/kernel/qopenglwindow.h b/src/gui/kernel/qopenglwindow.h
index 294bd90116f..e30de3b6acb 100644
--- a/src/gui/kernel/qopenglwindow.h
+++ b/src/gui/kernel/qopenglwindow.h
@@ -42,6 +42,10 @@
#ifndef QOPENGLWINDOW_H
#define QOPENGLWINDOW_H
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_OPENGL
+
#include <QtGui/QPaintDeviceWindow>
#include <QtGui/QOpenGLContext>
#include <QtGui/QImage>
@@ -97,4 +101,6 @@ private:
QT_END_NAMESPACE
+#endif // QT_NO_OPENGL
+
#endif
diff --git a/src/gui/opengl/qopengl.h b/src/gui/opengl/qopengl.h
index 65bfc7f8687..56e99ee8b8c 100644
--- a/src/gui/opengl/qopengl.h
+++ b/src/gui/opengl/qopengl.h
@@ -117,12 +117,6 @@ typedef char GLchar;
# include <QtGui/qopengles2ext.h>
# 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 <OpenGL/gl.h>
diff --git a/src/gui/opengl/qopenglfunctions.h b/src/gui/opengl/qopenglfunctions.h
index de1de39db21..b9e7523aadf 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
diff --git a/src/gui/opengl/qopenglgradientcache.cpp b/src/gui/opengl/qopenglgradientcache.cpp
index 91b4d084749..f8060fc6a05 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())
diff --git a/src/gui/opengl/qopenglvertexarrayobject.cpp b/src/gui/opengl/qopenglvertexarrayobject.cpp
index f39b10dc608..15f08ddfce4 100644
--- a/src/gui/opengl/qopenglvertexarrayobject.cpp
+++ b/src/gui/opengl/qopenglvertexarrayobject.cpp
@@ -391,6 +391,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()
{
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index eb197378ad7..549dce2923c 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) ||
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index cb3cb34d278..0a22038bb4c 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 09c70c50835..e23024e4720 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<GlyphAndSubPixelPosition, Glyph *> glyph_data; // maps from glyph index to glyph data
+ mutable QSet<glyph_t> missing_glyphs;
mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256
mutable int fast_glyph_count;
};
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 17bc4fde98a..2db8b3fc1bc 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;
diff --git a/src/network/access/qnetworkreply_p.h b/src/network/access/qnetworkreply_p.h
index ad11ef39648..55d3d855928 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 c5cf849a551..920dfdbb38e 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 06a5383ae42..b7de947a29d 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 616019ea410..be0ddf13884 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<qint64>(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 9edc0f6b596..3340dcc91eb 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<InternalNotifications> NotificationQueue;
QNetworkReplyImplPrivate();
diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp
index 2ea6d6e0153..4825d223eed 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<QSslSocket *>(parent->parent());
-#else
- d->sslSocket = Q_NULLPTR;
+ if (parent)
+ d->sslSocket = qobject_cast<QSslSocket *>(parent->parent());
#endif
connect(this, SIGNAL(connectionReady()), SLOT(connectionNotification()), Qt::QueuedConnection);
@@ -809,8 +807,8 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
return false;
}
EventRegistrationToken token;
- udpSocket()->add_MessageReceived(Callback<DatagramReceivedHandler>(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &token);
socketDescriptor = qintptr(socket.Detach());
+ udpSocket()->add_MessageReceived(Callback<DatagramReceivedHandler>(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &token);
return true;
}
default:
@@ -827,6 +825,7 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate()
, notifyOnException(false)
, closingDown(false)
, socketDescriptor(-1)
+ , sslSocket(Q_NULLPTR)
{
}
diff --git a/src/network/ssl/qasn1element.cpp b/src/network/ssl/qasn1element.cpp
index d282a02827a..f3f280d863c 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"));
@@ -155,6 +163,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 +213,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')) {
@@ -242,6 +273,30 @@ QMultiMap<QByteArray, QString> 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> QAsn1Element::toVector() const
{
QVector<QAsn1Element> items;
diff --git a/src/network/ssl/qasn1element_p.h b/src/network/ssl/qasn1element_p.h
index 6b3179ac358..36a7c90de32 100644
--- a/src/network/ssl/qasn1element_p.h
+++ b/src/network/ssl/qasn1element_p.h
@@ -59,11 +59,15 @@
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:
enum ElementType {
// universal
+ BooleanType = 0x01,
IntegerType = 0x02,
BitStringType = 0x03,
OctetStringType = 0x04,
@@ -77,10 +81,6 @@ public:
SequenceType = 0x30,
SetType = 0x31,
- // application
- Rfc822NameType = 0x81,
- DnsNameType = 0x82,
-
// context specific
Context0Type = 0xA0,
Context3Type = 0xA3
@@ -91,12 +91,15 @@ 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<QAsn1Element> &items);
static QAsn1Element fromObjectId(const QByteArray &id);
+ bool toBool(bool *ok = 0) const;
QDateTime toDateTime() const;
QMultiMap<QByteArray, QString> toInfo() const;
+ qint64 toInteger(bool *ok = 0) const;
QVector<QAsn1Element> toVector() const;
QByteArray toObjectId() const;
QByteArray toObjectName() const;
@@ -105,12 +108,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/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index bae78f43479..47ea3343ea5 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 <QtCore/qdir.h>
@@ -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 472553c30cd..b0c99e545dc 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<QSsl::AlternativeNameEntryType, QString> subjectAlternativeNames;
+ QList<QSslCertificateExtension> 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 391ee6f7f98..6ea78a408bb 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<QSslCertificateExtension> QSslCertificate::extensions() const
{
- Q_UNIMPLEMENTED();
- return QList<QSslCertificateExtension>();
+ return d->extensions;
}
#define BEGINCERTSTRING "-----BEGIN CERTIFICATE-----"
@@ -263,4 +270,249 @@ QList<QSslCertificate> 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<QAsn1Element> 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<QAsn1Element> 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_openssl.cpp b/src/network/ssl/qsslkey_openssl.cpp
index 7e78ac0fee4..6b0fa954eb0 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<QByteArray, QByteArray> 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 2b0dab9933e..b051ec68744 100644
--- a/src/network/ssl/qsslkey_p.cpp
+++ b/src/network/ssl/qsslkey_p.cpp
@@ -63,6 +63,7 @@
#include <QtCore/qatomic.h>
#include <QtCore/qbytearray.h>
+#include <QtCore/qbytearraymatcher.h>
#include <QtCore/qiodevice.h>
#ifndef QT_NO_DEBUG_STREAM
#include <QtCore/qdebug.h>
@@ -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<QByteArray, QByteArray> &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<QByteArray, QByteArray>::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<QByteArray, QByteArray> *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<QByteArray, QByteArray> 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 9c1476038ab..d24606e6a62 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<QByteArray, QByteArray> &headers) const;
+ QByteArray derFromPem(const QByteArray &pem, QMap<QByteArray, QByteArray> *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 feeb7d6f874..bc1ebc3c087 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 <QtCore/qcryptographichash.h>
+
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);
@@ -106,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())
@@ -117,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;
@@ -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<QByteArray, QByteArray> headers;
+ QByteArray data = derFromPem(pem, &headers);
+ if (headers.value("Proc-Type") == "4,ENCRYPTED") {
+ QList<QByteArray> dekInfo = headers.value("DEK-Info").split(',');
+ if (dekInfo.size() != 2) {
+ clear(deepClear);
+ return;
+ }
+
+ 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;
+ }
- decodeDer(derFromPem(pem), deepClear);
+ 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<QByteArray, QByteArray> 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 2c830696944..c5b4146ee9b 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<ISymmetricKeyAlgorithmProviderStatics> 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<ICryptographicEngineStatics> engine;
+ QHash<QSslKeyPrivate::Cipher, ComPtr<ISymmetricKeyAlgorithmProvider>> keyProviders;
+ ComPtr<ICryptographicBufferStatics> 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<IBuffer> keyBuffer;
+ hr = g->bufferFactory->CreateFromByteArray(key.length(), (BYTE *)key.data(), &keyBuffer);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<ICryptographicKey> 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<IBuffer> dataBuffer;
+ hr = g->bufferFactory->CreateFromByteArray(data.length(), (BYTE *)data.data(), &dataBuffer);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IBuffer> ivBuffer;
+ hr = g->bufferFactory->CreateFromByteArray(iv.length(), (BYTE *)iv.data(), &ivBuffer);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IBuffer> 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<Windows::Storage::Streams::IBufferByteAccess> 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<const char *>(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/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
index 148c5d9b2f5..dce8bd888c4 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/platformsupport/eglconvenience/qeglplatformcursor.cpp b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp
index b6293e60ec4..7198d7c6fb8 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 6f4216874aa..440bcc40ebb 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcursor_p.h
+++ b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h
@@ -44,6 +44,7 @@
#include <qpa/qplatformcursor.h>
#include <qpa/qplatformscreen.h>
+#include <QtGui/QOpenGLFunctions>
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 &region);
void createShaderPrograms();
- static void createCursorTexture(uint *texture, const QImage &image);
+ void createCursorTexture(uint *texture, const QImage &image);
void initCursorAtlas();
// current cursor information
diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp
index 26ae0eb7243..75359fbaa31 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);
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index de30fa825a5..7b761771416 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())
diff --git a/src/plugins/platforms/android/qandroideventdispatcher.cpp b/src/plugins/platforms/android/qandroideventdispatcher.cpp
index 074ba71f808..ab5070af9d8 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 8d1bcf21225..295763ce5ba 100644
--- a/src/plugins/platforms/android/qandroideventdispatcher.h
+++ b/src/plugins/platforms/android/qandroideventdispatcher.h
@@ -66,13 +66,14 @@ protected:
private:
QAtomicInt m_stopRequest;
QAtomicInt m_goingToStop;
- QSemaphore m_dispatcherSemaphore, m_stopperSemaphore;
+ QSemaphore m_semaphore;
};
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/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp
index 5d47d2fda47..90eff615a20 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 <QDebug>
#include <qevent.h>
#include <qguiapplication.h>
@@ -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<QInputMethodQueryEvent> 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<QInputMethodQueryEvent>();
QObject *focusObject = qGuiApp->focusObject();
if (!focusObject)
return QSharedPointer<QInputMethodQueryEvent>();
QSharedPointer<QInputMethodQueryEvent> ret = QSharedPointer<QInputMethodQueryEvent>(new QInputMethodQueryEvent(queries));
- if (qGuiApp->thread()==QThread::currentThread()) {
+ if (inMainThread) {
QCoreApplication::sendEvent(focusObject, ret.data());
} else {
QMetaObject::invokeMethod(this,
diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
index 73c0a76dd75..d3fb22094a6 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 <QSurfaceFormat>
#include <QtGui/private/qwindow_p.h>
@@ -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) {
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp
index be013f027b2..59b543e6d5b 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp
@@ -49,6 +49,7 @@
#include "qwindowscontext.h"
+#include <QtGui/QPainter>
#include <QtGui/QWindow>
#include <QtCore/QDebug>
@@ -85,9 +86,18 @@ QWindowsDirect2DBackingStore::~QWindowsDirect2DBackingStore()
{
}
-void QWindowsDirect2DBackingStore::beginPaint(const QRegion &)
+void QWindowsDirect2DBackingStore::beginPaint(const QRegion &region)
{
- 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 &region)
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp
index f5f4923b2fc..4bbe74b642b 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 c9d8607497e..33cc536b6db 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h
@@ -44,6 +44,7 @@
#include <QtCore/QScopedPointer>
#include <QtGui/QPaintDevice>
+#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 f1314191403..1d28befe417 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<ClipType> pushedClips;
+ QWindowsDirect2DPaintEngine::Flags flags;
QPointF currentBrushOrigin;
@@ -343,7 +345,7 @@ public:
D2D1::IdentityMatrix(),
1.0,
NULL,
- D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND),
+ D2D1_LAYER_OPTIONS1_NONE),
NULL);
pushedClips.push(LayerClip);
}
@@ -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
@@ -953,7 +956,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/qwindowsdirect2dpaintengine.h b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
index 1469d328761..4ed817b75fc 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 d9f7c595caf..88b440f857c 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 702ef7af922..69243abb1d0 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 <QtGui/qpa/qplatformpixmap.h>
#include <QtCore/QScopedPointer>
@@ -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 15ec0c35267..f739493c1a7 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
@@ -54,30 +54,15 @@ 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
- DXGI_SWAP_CHAIN_DESC1 desc = {};
-
- desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
- desc.SampleDesc.Count = 1;
- desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
- desc.BufferCount = 1;
- desc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
-
- HRESULT hr = QWindowsDirect2DContext::instance()->dxgiFactory()->CreateSwapChainForHwnd(
- QWindowsDirect2DContext::instance()->d3dDevice(), // [in] IUnknown *pDevice
- handle(), // [in] HWND hWnd
- &desc, // [in] const DXGI_SWAP_CHAIN_DESC1 *pDesc
- NULL, // [in] const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc
- NULL, // [in] IDXGIOutput *pRestrictToOutput
- m_swapChain.ReleaseAndGetAddressOf()); // [out] IDXGISwapChain1 **ppSwapChain
-
- if (FAILED(hr))
- qWarning("%s: Could not create swap chain: %#x", __FUNCTION__, hr);
+ if (m_directRendering)
+ setupSwapChain();
- hr = QWindowsDirect2DContext::instance()->d2dDevice()->CreateDeviceContext(
+ HRESULT hr = QWindowsDirect2DContext::instance()->d2dDevice()->CreateDeviceContext(
D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
m_deviceContext.GetAddressOf());
if (FAILED(hr))
@@ -88,6 +73,17 @@ 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();
@@ -97,13 +93,20 @@ QPixmap *QWindowsDirect2DWindow::pixmap()
void QWindowsDirect2DWindow::flush(QWindowsDirect2DBitmap *bitmap, const QRegion &region, 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);
+ 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();
@@ -116,7 +119,7 @@ void QWindowsDirect2DWindow::flush(QWindowsDirect2DBitmap *bitmap, const QRegion
ID2D1DeviceContext *dc = m_bitmap->deviceContext()->get();
if (!m_needsFullFlush) {
QRegion clipped = region;
- clipped &= QRect(0, 0, desc.Width, desc.Height);
+ clipped &= QRect(QPoint(), size);
foreach (const QRect &rect, clipped.rects()) {
QRectF rectF(rect);
@@ -127,7 +130,7 @@ void QWindowsDirect2DWindow::flush(QWindowsDirect2DBitmap *bitmap, const QRegion
to_d2d_rect_f(rectF.translated(offset.x(), offset.y())));
}
} else {
- QRectF rectF(0, 0, desc.Width, desc.Height);
+ QRectF rectF(QPoint(), size);
dc->DrawBitmap(bitmap->bitmap(),
to_d2d_rect_f(rectF),
1.0,
@@ -140,9 +143,66 @@ void QWindowsDirect2DWindow::flush(QWindowsDirect2DBitmap *bitmap, const QRegion
}
}
-void QWindowsDirect2DWindow::present()
+void QWindowsDirect2DWindow::present(const QRegion &region)
{
- m_swapChain->Present(0, 0);
+ if (m_directRendering) {
+ m_swapChain->Present(0, 0);
+ return;
+ }
+
+ ComPtr<IDXGISurface> bitmapSurface;
+ HRESULT hr = m_bitmap->bitmap()->GetSurface(&bitmapSurface);
+ Q_ASSERT(SUCCEEDED(hr));
+ ComPtr<IDXGISurface1> 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;
+ desc.SampleDesc.Count = 1;
+ desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ desc.BufferCount = 1;
+ desc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
+
+ HRESULT hr = QWindowsDirect2DContext::instance()->dxgiFactory()->CreateSwapChainForHwnd(
+ QWindowsDirect2DContext::instance()->d3dDevice(), // [in] IUnknown *pDevice
+ handle(), // [in] HWND hWnd
+ &desc, // [in] const DXGI_SWAP_CHAIN_DESC1 *pDesc
+ NULL, // [in] const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc
+ NULL, // [in] IDXGIOutput *pRestrictToOutput
+ m_swapChain.ReleaseAndGetAddressOf()); // [out] IDXGISwapChain1 **ppSwapChain
+
+ if (FAILED(hr))
+ qWarning("%s: Could not create swap chain: %#x", __FUNCTION__, hr);
+
+ 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<IDXGISurface1> 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<ID3D11Texture2D> 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<ID2D1Bitmap1> backBufferBitmap;
@@ -228,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));
}
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h
index 47c790da5da..6835c9cf6f5 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 &region, const QPoint &offset);
- void present();
+ void present(const QRegion &region);
+ void setupSwapChain();
void resizeSwapChain(const QSize &size);
QSharedPointer<QWindowsDirect2DBitmap> copyBackBuffer() const;
@@ -72,6 +75,7 @@ private:
QScopedPointer<QWindowsDirect2DBitmap> m_bitmap;
QScopedPointer<QPixmap> m_pixmap;
bool m_needsFullFlush;
+ bool m_directRendering;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/directfb/qdirectfbblitter.cpp b/src/plugins/platforms/directfb/qdirectfbblitter.cpp
index bc6e4d70e94..60a501f730d 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 c60f0fac25e..4fa432462fa 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
diff --git a/src/plugins/platforms/eglfs/eglfs.pri b/src/plugins/platforms/eglfs/eglfs.pri
index 6e3ba54b970..6f463ba7d91 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 00000000000..9e5d624d87c
--- /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 <QtPlatformSupport/private/qdevicediscovery_p.h>
+#include <QtCore/private/qcore_unix_p.h>
+#include <QtCore/QScopedPointer>
+#include <QtGui/qpa/qplatformwindow.h>
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <gbm.h>
+
+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<EGLNativeDisplayType>(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<EGLNativeWindowType>(m_gbm_surface);
+}
+
+void QEglKmsHooks::destroyNativeWindow(EGLNativeWindowType window)
+{
+ gbm_surface *surface = reinterpret_cast<gbm_surface *>(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<QEglKmsHooks::FrameBuffer *>(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<FrameBuffer *>(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<FrameBuffer> 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<bool *>(user_data) = false;
+}
+
+void QEglKmsHooks::waitForVSync() const
+{
+ const_cast<QEglKmsHooks*>(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;
+}
diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
index d770ea763a0..82269d07c68 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>(QEGLNativeContext(ctx->eglContext(), display));
return ctx;
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index d109d53168c..064098157db 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<QIOSInputContext> 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)
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm
index e8766654315..f1184be1b47 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();
@@ -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;
}
diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h
index bcff3e202ce..e55def1992f 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 d8dd875d836..aa33a9b21d8 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;
diff --git a/src/plugins/platforms/ios/quiview_textinput.mm b/src/plugins/platforms/ios/quiview_textinput.mm
index 2280b8259a4..6b2707e706b 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<QInputMethodEvent::Attribute> 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];
}
diff --git a/src/plugins/platforms/kms/qkmsscreen.cpp b/src/plugins/platforms/kms/qkmsscreen.cpp
index a930aa65450..3368af046f3 100644
--- a/src/plugins/platforms/kms/qkmsscreen.cpp
+++ b/src/plugins/platforms/kms/qkmsscreen.cpp
@@ -38,7 +38,6 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-//#include <QDebug>
#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 1fa8dbb763c..58237877a65 100644
--- a/src/plugins/platforms/kms/qkmsscreen.h
+++ b/src/plugins/platforms/kms/qkmsscreen.h
@@ -56,11 +56,14 @@ extern "C" {
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <QtGui/qopengl.h>
+#include <QtCore/qloggingcategory.h>
#include <qpa/qplatformscreen.h>
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen)
+
class QKmsCursor;
class QKmsDevice;
class QKmsContext;
diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro
index 584efa16652..69f6f308b5e 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/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index c62875d0ef4..8892fa6daac 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
@@ -46,6 +46,11 @@
#include <QtCore/QDebug>
#include <QtGui/QOpenGLContext>
+#if defined(QT_OPENGL_ES_2_ANGLE) || defined(QT_OPENGL_DYNAMIC)
+# define EGL_EGLEXT_PROTOTYPES
+# include <QtANGLE/EGL/eglext.h>
+#endif
+
QT_BEGIN_NAMESPACE
/*!
@@ -140,6 +145,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 +365,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;
@@ -512,6 +542,13 @@ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext,
if (pbuffer == EGL_NO_SURFACE)
return;
+ EGLDisplay prevDisplay = QWindowsEGLStaticContext::libEGL.eglGetCurrentDisplay();
+ if (prevDisplay == EGL_NO_DISPLAY) // when no context is current
+ prevDisplay = m_eglDisplay;
+ 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);
if (s) {
@@ -524,7 +561,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/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h
index 6c4ac08da16..a7866516f06 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,
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index e09018ef69f..869df26ef67 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 = QOpenGLStaticContext::opengl32.wglGetCurrentContext();
+ HDC prevSurface = QOpenGLStaticContext::opengl32.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/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
index 2e677102a58..96c4a8bb78f 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 a5a291a8d83..f491b51aa85 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)
@@ -439,6 +429,23 @@ static inline int indexOfMonitor(const QList<QWindowsScreenData> &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();
@@ -449,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;
}
}
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 49581db41af..44638bcbe01 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<QPlatformScreen *> 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 7d020ff9d6d..b6940e68504 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 <qpa/qwindowsysteminterface.h>
@@ -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 e6b996c6858..672d1699848 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 cb9da6fe271..03c71351bd9 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; }
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index 6c905735dd5..b981b94748e 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<IPointerPoint> 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);
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp
index d6fe5f3477c..3b13df863e1 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)
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 84d00d0e095..60a36a8da12 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)
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index fa5ccf58efd..e3fae73fd31 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)
diff --git a/src/src.pro b/src/src.pro
index 13f62137eca..ab93641131e 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/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp
index ae8206b8c37..243c8090dbb 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() << "<h" + QString::number(atom->string().toInt() + hOffset(relative)) + QLatin1Char('>');
+ case Atom::SectionHeadingLeft: {
+ int unit = atom->string().toInt() + hOffset(relative);
+ out() << "<h" + QString::number(unit) + QLatin1Char(' ');
+ if (unit < 3) {
+ out() << "id=\"" << Doc::canonicalTitle(Text::sectionHeading(atom).toString()) << "\"";
+ }
+ out() << ">";
inSectionHeading_ = true;
break;
+ }
case Atom::SectionHeadingRight:
out() << "</h" + QString::number(atom->string().toInt() + hOffset(relative)) + ">\n";
inSectionHeading_ = false;
@@ -1217,10 +1223,9 @@ void HtmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker)
else {
if (!s->members.isEmpty()) {
// out() << "<hr />\n";
- out() << "<a name=\""
- << registerRef((*s).name.toLower())
- << "\"></a>" << divNavTop << "\n";
- out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
+ QString ref = registerRef((*s).name.toLower());
+ out() << "<a name=\"" << ref << "\"></a>" << divNavTop << "\n";
+ out() << "<h2 id=\"" << ref << "\">" << protectEnc((*s).name) << "</h2>\n";
generateSection(s->members, inner, marker, CodeMarker::Summary);
}
if (!s->reimpMembers.isEmpty()) {
@@ -1255,13 +1260,14 @@ void HtmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker)
out() << "</ul>\n";
}
- out() << "<a name=\"" << registerRef("details") << "\"></a>" << divNavTop << '\n';
+ QString detailsRef = registerRef("details");
+ out() << "<a name=\"" << detailsRef << "\"></a>" << divNavTop << '\n';
if (!inner->doc().isEmpty()) {
generateExtractionMark(inner, DetailedDescriptionMark);
//out() << "<hr />\n"
out() << "<div class=\"descr\">\n" // QTBUG-9504
- << "<h2>" << "Detailed Description" << "</h2>\n";
+ << "<h2 id=\"" << detailsRef << "\">" << "Detailed Description" << "</h2>\n";
generateBody(inner, marker);
out() << "</div>\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() << "<a name=\"" << registerRef((*s).name.toLower())
+ QString ref = registerRef((*s).name.toLower());
+ out() << "<a name=\"" << ref
<< "\"></a>" << divNavTop << '\n';
- out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
+ out() << "<h2 id=\"" << ref << "\">" << protectEnc((*s).name) << "</h2>\n";
generateQmlSummary(*s, qcn, marker);
++s;
}
generateExtractionMark(qcn, DetailedDescriptionMark);
- out() << "<a name=\"" << registerRef("details") << "\"></a>" << divNavTop << '\n';
- out() << "<h2>" << "Detailed Description" << "</h2>\n";
+ QString detailsRef = registerRef("details");
+ out() << "<a name=\"" << detailsRef << "\"></a>" << divNavTop << '\n';
+ out() << "<h2 id=\"" << detailsRef << "\">" << "Detailed Description" << "</h2>\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() << "<a name=\"" << registerRef((*s).name) << "\"></a>" << divNavTop << '\n';
- out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
+ QString ref = registerRef((*s).name);
+ out() << "<a name=\"" << ref << "\"></a>" << divNavTop << '\n';
+ out() << "<h2 id=\"" << ref << "\">" << protectEnc((*s).name) << "</h2>\n";
generateSectionList(*s, dn, marker, CodeMarker::Summary);
++s;
}
@@ -1539,6 +1548,7 @@ void HtmlGenerator::generateCollectionNode(CollectionNode* cn, CodeMarker* marke
QList<Section> sections;
QList<Section>::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() << "<a name=\"" << registerRef("namespaces") << "\"></a>" << divNavTop << '\n';
- out() << "<h2>Namespaces</h2>\n";
+ ref = registerRef("namespaces");
+ out() << "<a name=\"" << ref << "\"></a>" << divNavTop << '\n';
+ out() << "<h2 id=\"" << ref << "\">Namespaces</h2>\n";
generateAnnotatedList(cn, marker, nm);
}
nm.clear();
cn->getMemberClasses(nm);
if (!nm.isEmpty()) {
- out() << "<a name=\"" << registerRef("classes") << "\"></a>" << divNavTop << '\n';
- out() << "<h2>Classes</h2>\n";
+ ref = registerRef("classes");
+ out() << "<a name=\"" << ref << "\"></a>" << divNavTop << '\n';
+ out() << "<h2 id=\"" << ref << "\">Classes</h2>\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() << "<a name=\"" << registerRef((*s).name) << "\"></a>" << divNavTop << '\n';
- out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
+ ref = registerRef((*s).name);
+ out() << "<a name=\"" << ref << "\"></a>" << divNavTop << '\n';
+ out() << "<h2 id=\"" << ref << "\">" << protectEnc((*s).name) << "</h2>\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() << "<a name=\"" << registerRef("details") << "\"></a>" << divNavTop << '\n';
+ ref = registerRef("details");
+ out() << "<a name=\"" << ref << "\"></a>" << divNavTop << '\n';
out() << "<div class=\"descr\">\n"; // QTBUG-9504
- out() << "<h2>" << "Detailed Description" << "</h2>\n";
+ out() << "<h2 id=\"" << ref << "\">" << "Detailed Description" << "</h2>\n";
}
else {
generateExtractionMark(cn, DetailedDescriptionMark);
@@ -2509,9 +2523,10 @@ QString HtmlGenerator::generateQmlMemberFile(QmlClassNode* qcn,
QList<Section>::const_iterator s = sections.constBegin();
while (s != sections.constEnd()) {
- out() << "<a name=\"" << registerRef((*s).name.toLower())
+ QString ref = registerRef((*s).name.toLower());
+ out() << "<a name=\"" << ref
<< "\"></a>" << divNavTop << '\n';
- out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
+ out() << "<h2 id=\"" << ref << "\">" << protectEnc((*s).name) << "</h2>\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<const EnumNode *>(node))->flagsType()) {
#ifdef GENERATE_MAC_REFS
generateMacRef(enume->flagsType(), marker);
#endif
- out() << "<h3 class=\"flags\">";
- out() << "<a name=\"" + refForNode(node) + "\"></a>";
+ out() << "<h3 class=\"flags\" id=\"" << nodeRef << "\">";
+ out() << "<a name=\"" + nodeRef + "\"></a>";
generateSynopsis(enume, relative, marker, CodeMarker::Detailed);
out() << "<br/>";
generateSynopsis(enume->flagsType(),
@@ -3831,8 +3847,8 @@ void HtmlGenerator::generateDetailedMember(const Node *node,
out() << "</h3>\n";
}
else {
- out() << "<h3 class=\"fn\">";
- out() << "<a name=\"" + refForNode(node) + "\"></a>";
+ out() << "<h3 class=\"fn\" id=\"" << nodeRef << "\">";
+ out() << "<a name=\"" + nodeRef + "\"></a>";
generateSynopsis(node, relative, marker, CodeMarker::Detailed);
out() << "</h3>" << divNavTop << '\n';
}
@@ -4051,6 +4067,7 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
#endif
generateExtractionMark(node, MemberMark);
out() << "<div class=\"qmlitem\">";
+ QString nodeRef = refForNode(node);
if (node->type() == Node::QmlPropertyGroup) {
const QmlPropertyGroupNode* qpgn = static_cast<const QmlPropertyGroupNode*>(node);
NodeList::ConstIterator p = qpgn->childNodes().constBegin();
@@ -4058,17 +4075,18 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
out() << "<table class=\"qmlname\">";
QString heading = qpgn->name() + " group";
- out() << "<tr valign=\"top\" class=\"even\">";
+ out() << "<tr valign=\"top\" class=\"even\" id=\"" << nodeRef << "\">";
out() << "<th class=\"centerAlign\"><p>";
- out() << "<a name=\"" + refForNode(qpgn) + "\"></a>";
+ out() << "<a name=\"" + nodeRef + "\"></a>";
out() << "<b>" << heading << "</b>";
out() << "</p></th></tr>";
while (p != qpgn->childNodes().constEnd()) {
if ((*p)->type() == Node::QmlProperty) {
qpn = static_cast<QmlPropertyNode*>(*p);
- out() << "<tr valign=\"top\" class=\"odd\">";
+ nodeRef = refForNode(qpn);
+ out() << "<tr valign=\"top\" class=\"odd\" id=\"" << nodeRef << "\">";
out() << "<td class=\"tblQmlPropNode\"><p>";
- out() << "<a name=\"" + refForNode(qpn) + "\"></a>";
+ out() << "<a name=\"" + nodeRef + "\"></a>";
if (!qpn->isWritable())
out() << "<span class=\"qmlreadonly\">read-only</span>";
@@ -4086,7 +4104,7 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
qpn = static_cast<QmlPropertyNode*>(node);
out() << "<div class=\"qmlproto\">";
out() << "<table class=\"qmlname\">";
- out() << "<tr valign=\"top\" class=\"odd\">";
+ out() << "<tr valign=\"top\" class=\"odd\" id=\"" << nodeRef << "\">";
out() << "<td class=\"tblQmlPropNode\"><p>";
out() << "<a name=\"" + refForNode(qpn) + "\"></a>";
if (!qpn->isReadOnlySet()) {
@@ -4106,7 +4124,7 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
const FunctionNode* qsn = static_cast<const FunctionNode*>(node);
out() << "<div class=\"qmlproto\">";
out() << "<table class=\"qmlname\">";
- out() << "<tr valign=\"top\" class=\"odd\">";
+ out() << "<tr valign=\"top\" class=\"odd\" id=\"" << nodeRef << "\">";
out() << "<td class=\"tblQmlFuncNode\"><p>";
out() << "<a name=\"" + refForNode(qsn) + "\"></a>";
generateSynopsis(qsn,relative,marker,CodeMarker::Detailed,false);
@@ -4118,7 +4136,7 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
const FunctionNode* qshn = static_cast<const FunctionNode*>(node);
out() << "<div class=\"qmlproto\">";
out() << "<table class=\"qmlname\">";
- out() << "<tr valign=\"top\" class=\"odd\">";
+ out() << "<tr valign=\"top\" class=\"odd\" id=\"" << nodeRef << "\">";
out() << "<td class=\"tblQmlFuncNode\"><p>";
out() << "<a name=\"" + refForNode(qshn) + "\"></a>";
generateSynopsis(qshn,relative,marker,CodeMarker::Detailed,false);
@@ -4130,7 +4148,7 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
const FunctionNode* qmn = static_cast<const FunctionNode*>(node);
out() << "<div class=\"qmlproto\">";
out() << "<table class=\"qmlname\">";
- out() << "<tr valign=\"top\" class=\"odd\">";
+ out() << "<tr valign=\"top\" class=\"odd\" id=\"" << nodeRef << "\">";
out() << "<td class=\"tblQmlFuncNode\"><p>";
out() << "<a name=\"" + refForNode(qmn) + "\"></a>";
generateSynopsis(qmn,relative,marker,CodeMarker::Detailed,false);
diff --git a/src/widgets/accessible/qaccessiblemenu.cpp b/src/widgets/accessible/qaccessiblemenu.cpp
index f47980d7867..82c36755089 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 cc6310d5915..b28f05cf8e4 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<QWidget*> 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 e8827f45375..d5933a68043 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<QLCDNumber*>(object())) {
QLCDNumber *l = qobject_cast<QLCDNumber*>(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)
@@ -729,8 +734,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 +746,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 +758,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/src/widgets/graphicsview/qgraphicsitem_p.h b/src/widgets/graphicsview/qgraphicsitem_p.h
index 4d1835f1780..7e3a01ef8b8 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 1cd162e6bb1..df74352e2bd 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/src/widgets/graphicsview/qgraphicsscene.h b/src/widgets/graphicsview/qgraphicsscene.h
index d95237baef8..ba47d45d639 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 baf3de37550..5788818394a 100644
--- a/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h
+++ b/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h
@@ -70,62 +70,50 @@ 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), m_numSortedElements(0)
{ }
QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::DescendingOrder) const
- {
- Q_UNUSED(order);
- return validList();
- }
+ { Q_UNUSED(order); return m_items; }
virtual QList<QGraphicsItem *> 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_numSortedElements = 0;
}
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;
- }
-
-private:
- mutable QList<QGraphicsItem*> m_items;
- mutable bool m_itemsIsValid;
+ // 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<QGraphicsItem*>& validList() const
- {
- if (!m_itemsIsValid)
+ QList<QGraphicsItem*>::iterator element = std::lower_bound(m_items.begin(), m_items.end(), item);
+ if (element != m_items.end() && *element == item)
{
- m_items.clear();
-
- QList<QGraphicsItem*> stack = scene()->d_func()->topLevelItems;
- m_items << stack;
- while (!stack.isEmpty())
- {
- m_items << stack.last()->childItems();
- stack << stack.takeLast()->childItems();
- }
- m_itemsIsValid = true;
+ m_items.erase(element);
+ --m_numSortedElements;
}
- return m_items;
}
+
+private:
+ QList<QGraphicsItem*> m_items;
+ int m_numSortedElements;
};
#endif // QT_NO_GRAPHICSVIEW
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index f438f60e472..3486396f549 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;
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index d8f31bfcc83..3dae22cdc7e 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
*/
/*!
@@ -880,6 +896,7 @@ void QOpenGLWidget::resizeEvent(QResizeEvent *e)
resizeGL(width(), height());
d->invokeUserPaint();
d->context->functions()->glFlush();
+ d->resolveSamples();
}
/*!
diff --git a/src/widgets/kernel/qopenglwidget.h b/src/widgets/kernel/qopenglwidget.h
index 28d802e1f40..f706ea75679 100644
--- a/src/widgets/kernel/qopenglwidget.h
+++ b/src/widgets/kernel/qopenglwidget.h
@@ -42,6 +42,10 @@
#ifndef QOPENGLWIDGET_H
#define QOPENGLWIDGET_H
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_OPENGL
+
#include <QtWidgets/QWidget>
#include <QtGui/QSurfaceFormat>
#include <QtGui/qopengl.h>
@@ -97,4 +101,6 @@ private:
QT_END_NAMESPACE
+#endif // QT_NO_OPENGL
+
#endif // QOPENGLWIDGET_H
diff --git a/src/widgets/kernel/qstandardgestures.cpp b/src/widgets/kernel/qstandardgestures.cpp
index e57c3285d29..48c2ad9e474 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();
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 34adea866e2..65978ef562e 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
}
}
@@ -7205,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
@@ -7262,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.)
@@ -7285,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();
diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp
index 2a968939e4c..103e244593b 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/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index cc24c79c098..ce6d3d708fa 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<const QStyleOptionHeader *>(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());
@@ -519,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) {
@@ -535,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
@@ -1642,30 +1645,33 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
break;
case CE_ToolBoxTabShape:
if (const QStyleOptionToolBox *tb = qstyleoption_cast<const QStyleOptionToolBox *>(opt)) {
+ p->setPen(tb->palette.mid().color().darker(150));
+ bool oldQt4CompatiblePainting = p->testRenderHint(QPainter::Qt4CompatiblePainting);
+ p->setRenderHint(QPainter::Qt4CompatiblePainting);
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);
+ 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 {
- 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);
+ 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->setPen(tb->palette.mid().color().darker(150));
- bool oldQt4CompatiblePainting = p->testRenderHint(QPainter::Qt4CompatiblePainting);
- p->setRenderHint(QPainter::Qt4CompatiblePainting);
- p->drawPolygon(a);
p->setRenderHint(QPainter::Qt4CompatiblePainting, oldQt4CompatiblePainting);
p->setPen(tb->palette.light().color());
if (tb->direction != Qt::RightToLeft) {
@@ -3037,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 <int N>
+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();
@@ -3061,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;
}
@@ -3569,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);
diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp
index 9ab8f8f08a3..2f04a20cd05 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,32 +305,123 @@ 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;
+}
+
+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
*/
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 = QWindowsStylePrivate::fixedPixelMetric(pm);
+ if (ret != QWindowsStylePrivate::InvalidMetric)
+ return int(QStyleHelper::dpiScaled(ret));
+
+ ret = 0;
switch (pm) {
- case PM_ButtonDefaultIndicator:
- case PM_ButtonShiftHorizontal:
- case PM_ButtonShiftVertical:
- case PM_MenuHMargin:
- case PM_MenuVMargin:
- ret = 1;
- break;
- case PM_DockWidgetSeparatorExtent:
- ret = int(QStyleHelper::dpiScaled(4.));
- break;
-#ifndef QT_NO_TABBAR
- case PM_TabBarTabShiftHorizontal:
- ret = 0;
- break;
- case PM_TabBarTabShiftVertical:
- ret = 2;
- break;
-#endif
case PM_MaximumDragDistance:
ret = QCommonStyle::pixelMetric(PM_MaximumDragDistance);
if (ret == -1)
@@ -328,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.
@@ -357,116 +454,18 @@ 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:
- 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;
-#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());
+ ret = qMax(int(QStyleHelper::dpiScaled(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;
default:
ret = QCommonStyle::pixelMetric(pm, opt, widget);
break;
@@ -909,7 +908,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)
diff --git a/src/widgets/styles/qwindowsstyle_p_p.h b/src/widgets/styles/qwindowsstyle_p_p.h
index 872b6f0e9e1..93994abf6db 100644
--- a/src/widgets/styles/qwindowsstyle_p_p.h
+++ b/src/widgets/styles/qwindowsstyle_p_p.h
@@ -68,7 +68,14 @@ 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 fixedPixelMetric(QStyle::PixelMetric pm);
+ 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 +97,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 e3699da7ef9..8b79a68f615 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);
@@ -459,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;
- 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;
@@ -541,7 +493,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 +545,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
return;
}
int bgType;
- pGetThemeEnumValue( theme.handle(),
+ QWindowsXPStylePrivate::pGetThemeEnumValue( theme.handle(),
partId,
stateId,
TMT_BGTYPE,
@@ -604,11 +556,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 +896,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);
@@ -1040,10 +992,10 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ToolBarTheme,
TP_DROPDOWNBUTTON);
if (theme.isValid()) {
- SIZE size;
- if (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);
@@ -1233,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);
- pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size);
- 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;
@@ -1291,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;
- pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size);
- 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;
@@ -1804,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);
@@ -1813,29 +1765,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);
- 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;
- 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) {
@@ -1933,15 +1877,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);
- pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size);
- pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins);
- minimumHeight = qMax<qint32>(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<const QStyleOptionMenuItem *>(option)) {
@@ -2001,7 +1946,7 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption
case SE_PushButtonContents:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(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 +1961,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,
@@ -2049,10 +1994,10 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption
int arrowWidth = 13;
int arrowHeight = 5;
if (theme.isValid()) {
- SIZE size;
- if (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) {
@@ -2245,7 +2190,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)
+ - int(QStyleHelper::dpiScaled(4));
const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget);
const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0;
@@ -2318,28 +2264,36 @@ QStyle::SubControl QWindowsVistaStyle::hitTestComplexControl(ComplexControl cont
return QWindowsXPStyle::hitTestComplexControl(control, option, pos, widget);
}
-/*!
- \internal
- */
-int QWindowsVistaStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
+int QWindowsVistaStylePrivate::fixedPixelMetric(QStyle::PixelMetric pm)
{
- 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:
+ 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 PM_MenuPanelWidth:
+ 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())
+ return QWindowsStyle::pixelMetric(metric, option, widget);
+
+ int ret = QWindowsStylePrivate::fixedPixelMetric(metric);
+ if (ret != QWindowsStylePrivate::InvalidMetric)
+ return int(QStyleHelper::dpiScaled(ret));
+
return QWindowsXPStyle::pixelMetric(metric, option, widget);
}
@@ -2382,9 +2336,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 +2446,6 @@ QPixmap QWindowsVistaStyle::standardPixmap(StandardPixmap standardPixmap, const
QWindowsVistaStylePrivate::QWindowsVistaStylePrivate() :
QWindowsXPStylePrivate(), m_treeViewHelper(0)
{
- resolveSymbols();
}
QWindowsVistaStylePrivate::~QWindowsVistaStylePrivate()
@@ -2511,43 +2464,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 +2500,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;
@@ -2619,14 +2535,13 @@ QIcon QWindowsVistaStyle::standardIcon(StandardPixmap standardIcon,
QWindowsXPStylePrivate::ButtonTheme,
BP_COMMANDLINKGLYPH, CMDLGS_NORMAL);
if (theme.isValid()) {
- SIZE size;
- 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/qwindowsvistastyle_p_p.h b/src/widgets/styles/qwindowsvistastyle_p_p.h
index f2f208fbb52..9f54ec8f21c 100644
--- a/src/widgets/styles/qwindowsvistastyle_p_p.h
+++ b/src/widgets/styles/qwindowsvistastyle_p_p.h
@@ -171,7 +171,7 @@ class QWindowsVistaStylePrivate : public QWindowsXPStylePrivate
public:
QWindowsVistaStylePrivate();
~QWindowsVistaStylePrivate();
- static bool resolveSymbols();
+ 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 e694eb4e7e5..8dc3c6cb48e 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()));
}
@@ -391,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;
}
@@ -1213,9 +1232,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 +1359,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 +1554,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 +1638,7 @@ case PE_Frame:
return;
}
int bgType;
- pGetThemeEnumValue( theme.handle(),
+ QWindowsXPStylePrivate::pGetThemeEnumValue( theme.handle(),
partId,
stateId,
TMT_BGTYPE,
@@ -1636,11 +1655,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 +1685,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++;
@@ -1982,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);
- 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<const QStyleOptionSizeGrip *>(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;
}
}
@@ -2055,10 +2073,9 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
QWindowsXPStylePrivate::ToolBarTheme,
TP_SPLITBUTTONDROPDOWN);
if (theme.isValid()) {
- SIZE size;
- 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;
@@ -2450,10 +2467,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),
@@ -2741,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);
@@ -2750,28 +2766,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);
- 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;
- 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()) {
@@ -3062,10 +3069,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(),
@@ -3093,9 +3100,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
} else {
theme.partId = partId;
theme.stateId = stateId;
- SIZE sz;
- 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();
@@ -3310,23 +3315,63 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
}
}
+static inline Qt::Orientation progressBarOrientation(const QStyleOption *option = 0)
+{
+ if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(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<const QListView*>(widget))
- res = 2;
- else
- res = 1;
+ res = qobject_cast<const QListView*>(widget) ? 2 : 1;
break;
case PM_MenuPanelWidth:
case PM_SpinBoxFrameWidth:
@@ -3344,6 +3389,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:
@@ -3354,10 +3401,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;
@@ -3366,77 +3409,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;
- 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;
- 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<const QStyleOptionProgressBarV2 *>(option))
- orient = pb2->orientation;
- XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ProgressTheme,
- (orient == Qt::Horizontal) ? PP_CHUNK : PP_CHUNKVERT);
- if (theme.isValid()) {
- SIZE size;
- 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;
- 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;
- pGetThemePartSize(theme.handle(), 0, WP_FRAMELEFT, FS_ACTIVE, 0, TS_TRUE, &size);
- res = size.cx-1;
- }
- }
- break;
-
case PM_MdiSubWindowMinimizedWidth:
res = 160;
break;
@@ -3447,33 +3419,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;
- 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<const QStyleOptionToolButton *>(option))
- res = 1;
- else
- res = 0;
- break;
-
- case PM_ButtonDefaultIndicator:
- res = 0;
+ res = qstyleoption_cast<const QStyleOptionToolButton *>(option) ? 1 : 0;
break;
default:
@@ -3553,8 +3506,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 = int(QStyleHelper::dpiScaled(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);
@@ -3746,20 +3702,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 = 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)
@@ -3929,9 +3877,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;
- 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);
}
}
}
@@ -3964,13 +3911,12 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon,
XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme,
WP_MAXBUTTON, MAXBS_NORMAL);
if (theme.isValid()) {
- SIZE size;
- 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);
@@ -3999,14 +3945,13 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon,
XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme,
WP_SMALLCLOSEBUTTON, CBS_NORMAL);
if (theme.isValid()) {
- SIZE size;
- 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);
@@ -4036,13 +3981,12 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon,
XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme,
WP_RESTOREBUTTON, RBS_NORMAL);
if (theme.isValid()) {
- SIZE size;
- 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 7327fa55811..6e1cfe6db51 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;
@@ -282,7 +292,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:
@@ -316,6 +384,9 @@ public:
~QWindowsXPStylePrivate()
{ 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);
void init(bool force = false);
@@ -374,6 +445,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
diff --git a/src/widgets/util/qscroller.cpp b/src/widgets/util/qscroller.cpp
index 235cbc78652..abbba870390 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/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp
index 1b484419931..0e78c1493bd 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
diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp
index 2eb04d146e3..213e72183ff 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/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp
index 7ad893a54e9..58ec068bb25 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);
diff --git a/src/widgets/widgets/qmdisubwindow.cpp b/src/widgets/widgets/qmdisubwindow.cpp
index 5521d866b2b..5166c3cf385 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<QMouseEvent *>(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()));
}
diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp
index df13085dee7..3f34a08b5e0 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){
diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
index 0389ae79766..076e3eee1c7 100644
--- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
+++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
@@ -45,6 +45,8 @@
#include <QPair>
#include <QTextCodec>
+#include <QSysInfo>
+#include <QLatin1String>
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"
diff --git a/tests/auto/corelib/tools/qelapsedtimer/tst_qelapsedtimer.cpp b/tests/auto/corelib/tools/qelapsedtimer/tst_qelapsedtimer.cpp
index f2852f6a501..48e3745be42 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());
diff --git a/tests/auto/gui/kernel/qwindow/qwindow.pro b/tests/auto/gui/kernel/qwindow/qwindow.pro
index e419a104406..52105857966 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
diff --git a/tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp b/tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp
index 661d13bc694..92b603473be 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<QAsn1Element>("a");
+ QTest::addColumn<QAsn1Element>("b");
+ QTest::addColumn<bool>("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<QByteArray>("encoded");
+ QTest::addColumn<bool>("value");
+ QTest::addColumn<bool>("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<QByteArray>("encoded");
@@ -122,6 +182,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);
diff --git a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
index cc90be00a2a..229ce4abb5b 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();
@@ -927,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 ||
@@ -975,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
@@ -1059,9 +1060,6 @@ void tst_QSslCertificate::extensions()
QSslCertificate cert = certList[0];
QList<QSslCertificateExtension> 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;
@@ -1096,6 +1094,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 +1107,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<QString>() << QStringLiteral("OCSP") << QStringLiteral("caIssuers"));
QString ocsp = aiaValue[QStringLiteral("OCSP")].toString();
QString caIssuers = aiaValue[QStringLiteral("caIssuers")].toString();
@@ -1119,25 +1122,76 @@ 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<QString>() << 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<QString>() << QStringLiteral("keyid"));
QVERIFY(authValue[QStringLiteral("keyid")].toByteArray() ==
QByteArray("4e43c81d76ef37537a4ff2586f94f338e2d5bddf"));
+}
+
+void tst_QSslCertificate::extensionsCritical()
+{
+ QList<QSslCertificate> 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<QSslCertificateExtension> extensions = cert.extensions();
+ 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<QString>() << 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
@@ -1254,7 +1308,7 @@ void tst_QSslCertificate::pkcs12()
QSslCertificate cert;
QList<QSslCertificate> 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);
diff --git a/tests/auto/network/ssl/qsslkey/qsslkey.pro b/tests/auto/network/ssl/qsslkey/qsslkey.pro
index 78cfb9ce922..4ec4f27e6fc 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 00000000000..7a0722fb8dd
--- /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 642b115bee7..1c16f47ad63 100644
--- a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
+++ b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
@@ -47,6 +47,11 @@
#include <QtNetwork/qhostaddress.h>
#include <QtNetwork/qnetworkproxy.h>
+#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<QSslKeyPrivate::Cipher>("cipher");
+ QTest::addColumn<QByteArray>("key");
+ QTest::addColumn<QByteArray>("plainText");
+ QTest::addColumn<QByteArray>("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)
diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
index 33cee37b92b..295b60e739d 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()
{
@@ -1992,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<QVariantList> &peerVerifyList = peerVerifyErrorSpy;
+ foreach (const QVariantList &args, peerVerifyList)
+ peerErrors << qvariant_cast<QSslError>(args.first()).error();
+ QVERIFY(peerErrors.contains(QSslError::HostNameMismatch));
+
+ // check HostNameMismatch was emitted by sslErrors
QVERIFY(!sslErrorsSpy.isEmpty());
- QCOMPARE(qvariant_cast<QSslError>(peerVerifyErrorSpy.last().at(0)).error(), QSslError::HostNameMismatch);
- QCOMPARE(qvariant_cast<QList<QSslError> >(sslErrorsSpy.at(0).at(0)).size(), peerVerifyErrorSpy.size());
+ SslErrorList sslErrors;
+ foreach (const QSslError &err, qvariant_cast<QList<QSslError> >(sslErrorsSpy.first().first()))
+ sslErrors << err.error();
+ QVERIFY(peerErrors.contains(QSslError::HostNameMismatch));
+
+ QCOMPARE(sslErrors.size(), peerErrors.size());
}
void tst_QSslSocket::disconnectFromHostWhenConnecting()
@@ -2280,6 +2299,7 @@ void tst_QSslSocket::versionAccessors()
qDebug() << QString::number(QSslSocket::sslLibraryVersionNumber(), 16);
}
+#ifndef QT_NO_OPENSSL
void tst_QSslSocket::sslOptions()
{
if (!QSslSocket::supportsSsl())
@@ -2331,6 +2351,7 @@ void tst_QSslSocket::sslOptions()
#endif
#endif
}
+#endif
void tst_QSslSocket::encryptWithoutConnecting()
{
diff --git a/tests/auto/other/other.pro b/tests/auto/other/other.pro
index 745c8f24999..bd3997f8c9f 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 -= \
diff --git a/tests/auto/other/qaccessibility/accessiblewidgets.h b/tests/auto/other/qaccessibility/accessiblewidgets.h
new file mode 100644
index 00000000000..c15cd43f851
--- /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 <QtWidgets/qaccessiblewidget.h>
+#include <QtWidgets/qpushbutton.h>
+
+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<QtTestAccessibleWidget*>(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<CustomTextWidget*>(o));
+ return 0;
+ }
+ CustomTextWidgetIface(CustomTextWidget *w): QAccessibleWidget(w) {}
+ void *interface_cast(QAccessible::InterfaceType t) {
+ if (t == QAccessible::TextInterface)
+ return static_cast<QAccessibleTextInterface*>(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<CustomTextWidget *>(widget()); }
+};
+
+#endif // ACCESSIBLEWIDGETS_H
diff --git a/tests/auto/other/qaccessibility/qaccessibility.pro b/tests/auto/other/qaccessibility/qaccessibility.pro
index e6c5bb11494..8d445437df3 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 d3c9aa87ef2..68723e9c2ff 100644
--- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
+++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
@@ -69,6 +69,8 @@
#include <algorithm>
+#include "accessiblewidgets.h"
+
// Make a widget frameless to prevent size constraints of title bars
// from interfering (Windows).
static inline void setFrameless(QWidget *w)
@@ -260,6 +262,8 @@ private slots:
void lineEditTest();
void lineEditTextFunctions_data();
void lineEditTextFunctions();
+ void textInterfaceTest_data();
+ void textInterfaceTest();
void groupBoxTest();
void dialogButtonBoxTest();
void dialTest();
@@ -389,43 +393,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<QtTestAccessibleWidget*>(o));
- return 0;
- }
-};
-
-class QtTestAccessibleWidgetSubclass: public QtTestAccessibleWidget
-{
- Q_OBJECT
-public:
- QtTestAccessibleWidgetSubclass(QWidget *parent, const char *name): QtTestAccessibleWidget(parent, name)
- {}
-};
-
void tst_QAccessibility::customWidget()
{
{
@@ -485,14 +452,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);
@@ -2375,6 +2334,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()
{
{
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
index c89b05616da..8847a5748f3 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"
diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp
index 3471ed78aeb..ddfb1d955bf 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 -----------------------------------------------