summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 7cbd11d98d..0c65aac14a 100755
--- a/configure
+++ b/configure
@@ -6636,7 +6636,7 @@ if [ "$CFG_OPENSSL" = "linked" ] && [ "$OPENSSL_LIBS" = "" ]; then
echo "For example:"
echo " OPENSSL_LIBS='-L/opt/ssl/lib -lssl -lcrypto' ./configure -openssl-linked"
fi
-if [ "$CFG_JOURNALD" = "yes" ] || [ "$CFG_SLOG2" = "yes"]; then
+if [ "$CFG_JOURNALD" = "yes" ] || [ "$CFG_SLOG2" = "yes" ]; then
echo
echo "NOTE: journald or slog2 integration is enabled."
echo "If your users intend on developing applications against this build,"
diff --git a/doc/global/externalsites.qdocconf b/doc/global/externalsites.qdocconf
new file mode 100644
index 0000000000..46ce8401c0
--- /dev/null
+++ b/doc/global/externalsites.qdocconf
@@ -0,0 +1,3 @@
+# Include the external websites
+sourcedirs += externalsites
+
diff --git a/doc/global/fileextensions.qdocconf b/doc/global/fileextensions.qdocconf
index ec47dc9c7f..0a106d5bef 100644
--- a/doc/global/fileextensions.qdocconf
+++ b/doc/global/fileextensions.qdocconf
@@ -8,5 +8,3 @@ examples.imageextensions = "*.png *.jpg *.gif"
headers.fileextensions = "*.ch *.h *.h++ *.hh *.hpp *.hxx"
sources.fileextensions = "*.c++ *.cc *.cpp *.cxx *.mm *.qml *.qdoc"
-#include the external websites
-sourcedirs += externalsites
diff --git a/doc/global/template/style/offline.css b/doc/global/template/style/offline.css
index 7fc0d62fa6..5957e3840d 100644
--- a/doc/global/template/style/offline.css
+++ b/doc/global/template/style/offline.css
@@ -97,6 +97,10 @@ a[href*="http://"], a[href*="ftp://"], a[href*="https://"] {
text-height: 24px;
}
+.flags:target {
+ background-color: #FFFFD6;
+}
+
/*
-------------------------------
NOTE styles
@@ -327,6 +331,10 @@ h2, p.h2 {
max-width: 99%;
}
+h2:target {
+ background-color: #F2F3D4;
+}
+
h3 {
font: 500 14px/1.2 Arial;
font-weight: 100;
@@ -353,6 +361,10 @@ h3.fn, span.fn {
margin-top: 45px;
}
+h3.fn:target {
+ background-color: #F6F6D6;
+}
+
.name {
color: #1A1A1A
}
@@ -413,6 +425,10 @@ table, pre {
color: #66666E;
}
+ table tr:target {
+ background-color: #F6F6D6;
+ }
+
table thead {
text-align: left;
padding-left: 20px;
diff --git a/doc/global/template/style/online.css b/doc/global/template/style/online.css
index 0dc01d396b..5d0cd7ecfb 100644
--- a/doc/global/template/style/online.css
+++ b/doc/global/template/style/online.css
@@ -48,6 +48,10 @@ links
text-height: 24px;
}
+.flags:target {
+ background-color: #FFFFD6;
+}
+
/*
-------------------------------
NOTE styles
@@ -204,6 +208,10 @@ h2, p.h2 {
overflow: hidden;
}
+h2:target {
+ background-color: #F2F3D4;
+}
+
h3 {
font: 500 14px/1.2 Arial;
font-weight: 100;
@@ -212,6 +220,10 @@ h3 {
margin-top: 30px;
}
+h3.fn:target {
+ background-color: #F6F6D6;
+}
+
h3.fn, span.fn {
border-width: 1px;
border-style: solid;
@@ -293,6 +305,10 @@ table, pre {
color: #66666E;
}
+ table tr:target {
+ background-color: #F6F6D6;
+ }
+
table thead {
text-align: left;
padding-left: 20px;
diff --git a/examples/opengl/hellowindow/hellowindow.cpp b/examples/opengl/hellowindow/hellowindow.cpp
index da31fee920..57eb111edb 100644
--- a/examples/opengl/hellowindow/hellowindow.cpp
+++ b/examples/opengl/hellowindow/hellowindow.cpp
@@ -147,6 +147,21 @@ void Renderer::render()
f->glViewport(0, 0, viewSize.width() * surface->devicePixelRatio(), viewSize.height() * surface->devicePixelRatio());
f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ f->glClearColor(0.1f, 0.1f, 0.2f, 1.0f);
+ f->glFrontFace(GL_CW);
+ f->glCullFace(GL_FRONT);
+ f->glEnable(GL_CULL_FACE);
+ f->glEnable(GL_DEPTH_TEST);
+
+ m_program->bind();
+ m_vbo.bind();
+
+ m_program->enableAttributeArray(vertexAttr);
+ m_program->enableAttributeArray(normalAttr);
+ m_program->setAttributeBuffer(vertexAttr, GL_FLOAT, 0, 3);
+ const int verticesSize = vertices.count() * 3 * sizeof(GLfloat);
+ m_program->setAttributeBuffer(normalAttr, GL_FLOAT, verticesSize, 3);
+
QMatrix4x4 modelview;
modelview.rotate(m_fAngle, 0.0f, 1.0f, 0.0f);
modelview.rotate(m_fAngle, 1.0f, 0.0f, 0.0f);
@@ -212,18 +227,6 @@ void Renderer::initialize()
m_vbo.allocate(verticesSize * 2);
m_vbo.write(0, vertices.constData(), verticesSize);
m_vbo.write(verticesSize, normals.constData(), verticesSize);
-
- QOpenGLFunctions *f = m_context->functions();
- f->glClearColor(0.1f, 0.1f, 0.2f, 1.0f);
- f->glFrontFace(GL_CW);
- f->glCullFace(GL_FRONT);
- f->glEnable(GL_CULL_FACE);
- f->glEnable(GL_DEPTH_TEST);
-
- m_program->enableAttributeArray(vertexAttr);
- m_program->enableAttributeArray(normalAttr);
- m_program->setAttributeBuffer(vertexAttr, GL_FLOAT, 0, 3);
- m_program->setAttributeBuffer(normalAttr, GL_FLOAT, verticesSize, 3);
}
void Renderer::createGeometry()
diff --git a/qmake/doc/snippets/code/doc_src_qmake-manual.pro b/qmake/doc/snippets/code/doc_src_qmake-manual.pro
index 07bed62763..1bd89d2f04 100644
--- a/qmake/doc/snippets/code/doc_src_qmake-manual.pro
+++ b/qmake/doc/snippets/code/doc_src_qmake-manual.pro
@@ -970,3 +970,15 @@ int main() { return featureFunction(); }
# <project 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 ad08f729a7..52fc1ec4fb 100644
--- a/qmake/doc/src/qmake-manual.qdoc
+++ b/qmake/doc/src/qmake-manual.qdoc
@@ -2071,6 +2071,39 @@
qmake or \l{#QMAKESPEC}{qmake.conf} and rarely
needs to be modified.
+ \section1 QMAKE_SONAME_PREFIX
+
+ If defined, the value of this variable is used as a path to be prepended to
+ the built shared library's \c SONAME identifier. The \c SONAME is the
+ identifier that the dynamic linker will later use to reference the library.
+ In general this reference may be a library name or full library path. On OS
+ X and iOS, the path may be specified relatively using the following
+ placeholders:
+
+ \table
+ \header \li Placeholder \li Effect
+ \row \li @rpath
+ \li Expands to paths defined by LC_RPATH mach-o commands in
+ the current process executable or the referring libraries.
+ \row \li @executable_path
+ \li Expands to the current process executable location.
+ \row \li @loader_path
+ \li Expands to the referring executable or library location.
+ \endtable
+
+ In most cases, using \c @rpath is sufficient and recommended:
+
+ \snippet code/doc_src_qmake-manual.pro 183
+
+ However, the prefix may be also specified using different placeholders, or
+ an absolute path, such as one of the following:
+
+ \snippet code/doc_src_qmake-manual.pro 184
+
+ For more information, see
+ \l{https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/dyld.1.html}{dyld}
+ documentation on dynamic library install names.
+
\section1 QMAKE_TARGET
Specifies the name of the project target. The value of this
diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp
index e16e0f5c20..c68cebfd8c 100644
--- a/qmake/generators/unix/unixmake2.cpp
+++ b/qmake/generators/unix/unixmake2.cpp
@@ -1265,6 +1265,13 @@ void UnixMakefileGenerator::init2()
if(!instpath.endsWith(Option::dir_sep))
instpath += Option::dir_sep;
soname.prepend(instpath);
+ } else if (!project->isEmpty("QMAKE_SONAME_PREFIX")) {
+ QString sonameprefix = project->first("QMAKE_SONAME_PREFIX").toQString();
+ if (!sonameprefix.startsWith('@') && !sonameprefix.startsWith('$'))
+ sonameprefix = Option::fixPathToTargetOS(sonameprefix, false);
+ if (!sonameprefix.endsWith(Option::dir_sep))
+ sonameprefix += Option::dir_sep;
+ soname.prepend(sonameprefix);
}
project->values("QMAKE_LFLAGS_SONAME").first() += escapeFilePath(soname);
}
diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
index cedc6f2f22..44c5c7c03b 100644
--- a/src/3rdparty/angle/src/common/platform.h
+++ b/src/3rdparty/angle/src/common/platform.h
@@ -59,8 +59,10 @@
# include <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 8201acda10..99df85b0d3 100644
--- a/src/3rdparty/angle/src/libGLESv2/Context.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp
@@ -368,7 +368,7 @@ void Context::deleteFenceSync(GLsync fenceSync)
// wait commands finish. However, since the name becomes invalid, we cannot query the fence,
// and since our API is currently designed for being called from a single thread, we can delete
// the fence immediately.
- mResourceManager->deleteFenceSync(reinterpret_cast<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 352da9654a..1301124b2d 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp
@@ -12,6 +12,10 @@
#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
+#if defined(__MINGW32__) && !defined(D3D11_MAP_FLAG_DO_NOT_WAIT)
+# define D3D11_MAP_FLAG_DO_NOT_WAIT 0x100000L
+#endif
+
namespace rx
{
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
index 8db5ea27c1..5121950da0 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
@@ -116,8 +116,8 @@ Clear11::Clear11(Renderer11 *renderer)
mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat);
if (mRenderer->isLevel9()) {
- mUintClearShader = { 0 };
- mIntClearShader = { 0 };
+ memset(&mUintClearShader, 0, sizeof(ClearShader));
+ memset(&mIntClearShader, 0, sizeof(ClearShader));
return;
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp
index 17cf5cad47..e5e00325b2 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp
@@ -12,6 +12,14 @@
#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
#include "libGLESv2/main.h"
+#if defined(__MINGW32__) // Provide undefined struct
+typedef struct D3D11_QUERY_DATA_SO_STATISTICS
+{
+ UINT64 NumPrimitivesWritten;
+ UINT64 PrimitivesStorageNeeded;
+} D3D11_QUERY_DATA_SO_STATISTICS;
+#endif
+
namespace rx
{
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h
index ba9f76e5de..82182957af 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h
@@ -51,4 +51,4 @@ class RenderTarget11 : public RenderTarget
}
-#endif LIBGLESV2_RENDERER_RENDERTARGET11_H_
+#endif // LIBGLESV2_RENDERER_RENDERTARGET11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
index 651b065ca2..3ba0cc767b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
@@ -49,6 +49,31 @@
#define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1
#endif
+#ifndef D3D11_PS_INPUT_REGISTER_COUNT
+# define D3D11_PS_INPUT_REGISTER_COUNT 32
+#endif
+#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT
+# define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32
+#endif
+#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT
+# define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14
+#endif
+#ifndef D3D11_SO_BUFFER_SLOT_COUNT
+# define D3D11_SO_BUFFER_SLOT_COUNT 4
+#endif
+#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT
+# define D3D10_1_SO_BUFFER_SLOT_COUNT 4
+#endif
+#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT
+# define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096
+#endif
+#ifndef D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP
+# define D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP 32
+#endif
+#ifndef D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP
+# define D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP 32
+#endif
+
namespace rx
{
static const DXGI_FORMAT RenderTargetFormats[] =
@@ -275,7 +300,7 @@ EGLint Renderer11::initialize()
}
// Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
-#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
+#if !defined(__MINGW32__) && defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
ID3D11InfoQueue *infoQueue;
result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
index a31f15ee64..b54f75d859 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
@@ -261,7 +261,7 @@ class Renderer11 : public Renderer
};
MultisampleSupportInfo getMultisampleSupportInfo(DXGI_FORMAT format);
- typedef std::unordered_map<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 d3d135fe5b..d914a8201b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -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 b4b483b416..c85104b11e 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
@@ -45,6 +45,7 @@ package org.qtproject.qt5.android;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
@@ -110,6 +111,7 @@ public class QtActivityDelegate
private String m_mainLib;
private long m_metaState;
private int m_lastChar = 0;
+ private int m_softInputMode = 0;
private boolean m_fullScreen = false;
private boolean m_started = false;
private HashMap<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 78b53dfa14..c454fee8f9 100644
--- a/src/angle/angle.pro
+++ b/src/angle/angle.pro
@@ -6,6 +6,5 @@ SUBDIRS += src
# 2) If we made a 'QtANGLE' module, the include directory would be flattened which won't work since
# we need to support "#include <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 0000000000..dcff4a323e
--- /dev/null
+++ b/src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch
@@ -0,0 +1,203 @@
+From bfcd8298f9ba074116de434bf252ea95be968a20 Mon Sep 17 00:00:00 2001
+From: Andrew Knight <andrew.knight@digia.com>
+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 0000000000..3cf6c67d16
--- /dev/null
+++ b/src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch
@@ -0,0 +1,175 @@
+From ac4e9bb72ca22fd39bfc43f087108694db2ae8ac Mon Sep 17 00:00:00 2001
+From: Andrew Knight <andrew.knight@digia.com>
+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 ccc4cb16a1..07a18620da 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 dc286ca11d..48ce7055fd 100644
--- a/src/angle/src/libEGL/libEGL.pro
+++ b/src/angle/src/libEGL/libEGL.pro
@@ -1,10 +1,7 @@
CONFIG += installed
include(../common/common.pri)
-angle_d3d11: \
- LIBS_PRIVATE += -ld3d11
-!winrt: \
- LIBS_PRIVATE += -ld3d9
+winrt: LIBS_PRIVATE += -ld3d11
LIBS_PRIVATE += -ldxguid -L$$QT_BUILD_TREE/lib -l$$qtLibraryTarget(libGLESv2)
diff --git a/src/angle/src/libGLESv2/libGLESv2.pro b/src/angle/src/libGLESv2/libGLESv2.pro
index 8109c34942..2e84df0d39 100644
--- a/src/angle/src/libGLESv2/libGLESv2.pro
+++ b/src/angle/src/libGLESv2/libGLESv2.pro
@@ -4,12 +4,10 @@ include(../common/common.pri)
INCLUDEPATH += $$OUT_PWD/.. $$ANGLE_DIR/src/libGLESv2
# Remember to adapt tools/configure/configureapp.cpp if the Direct X version changes.
-angle_d3d11: \
- LIBS_PRIVATE += -ldxgi -ld3d11
!winrt: \
LIBS_PRIVATE += -ld3d9
winrt: \
- LIBS_PRIVATE += -ld3dcompiler
+ LIBS_PRIVATE += -ld3dcompiler -ldxgi -ld3d11
LIBS_PRIVATE += -ldxguid
diff --git a/src/corelib/global/archdetect.cpp b/src/corelib/global/archdetect.cpp
index e35595e727..344c363031 100644
--- a/src/corelib/global/archdetect.cpp
+++ b/src/corelib/global/archdetect.cpp
@@ -83,10 +83,10 @@
# define ARCH_PROCESSOR "unknown"
#endif
-// endinanness
-#if defined(Q_LITTLE_ENDIAN)
+// endianness
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
# define ARCH_ENDIANNESS "little_endian"
-#elif defined(Q_BIG_ENDIAN)
+#elif Q_BYTE_ORDER == Q_BIG_ENDIAN
# define ARCH_ENDIANNESS "big_endian"
#endif
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 3bf1cc0cbb..2c7a00133d 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -742,7 +742,6 @@
# define Q_COMPILER_DEFAULT_MEMBERS
# define Q_COMPILER_DELETE_MEMBERS
# define Q_COMPILER_EXTERN_TEMPLATES
-# define Q_COMPILER_INITIALIZER_LISTS
# define Q_COMPILER_UNIFORM_INIT
# define Q_COMPILER_UNICODE_STRINGS
# define Q_COMPILER_VARIADIC_TEMPLATES
@@ -750,6 +749,9 @@
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
/* C++11 features supported in GCC 4.5: */
# define Q_COMPILER_EXPLICIT_CONVERSIONS
+ /* GCC 4.4 implements initializer_list but does not define typedefs required
+ * by the standard. */
+# define Q_COMPILER_INITIALIZER_LISTS
# define Q_COMPILER_LAMBDA
# define Q_COMPILER_RAW_STRINGS
# endif
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 0647513221..5fe1047426 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -310,7 +310,7 @@ struct DefinedTypesFilter {
name to a type so that it can be created and destructed
dynamically at run-time. Declare new types with Q_DECLARE_METATYPE()
to make them available to QVariant and other template-based functions.
- Call qRegisterMetaType() to make type available to non-template based
+ Call qRegisterMetaType() to make types available to non-template based
functions, such as the queued signal and slot connections.
Any class or struct that has a public default
diff --git a/src/corelib/kernel/qtcore_eval.cpp b/src/corelib/kernel/qtcore_eval.cpp
index a5c4c36638..c938e0fb5b 100644
--- a/src/corelib/kernel/qtcore_eval.cpp
+++ b/src/corelib/kernel/qtcore_eval.cpp
@@ -119,9 +119,11 @@ static EvaluationStatus qt_eval_is_supported()
static int qt_eval_days_left()
{
+ const char *expiry_date = const_cast<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 fb5c5f5943..edb4f4e048 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 1da85fce96..08fc1cf5e2 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 b06afe4ab4..7df5dec63a 100644
--- a/src/corelib/tools/qelapsedtimer.h
+++ b/src/corelib/tools/qelapsedtimer.h
@@ -57,6 +57,13 @@ public:
MachAbsoluteTime,
PerformanceCounter
};
+
+ Q_DECL_CONSTEXPR QElapsedTimer()
+ : t1(Q_INT64_C(0x8000000000000000))
+ , t2(Q_INT64_C(0x8000000000000000))
+ {
+ }
+
static ClockType clockType() Q_DECL_NOTHROW;
static bool isMonotonic() Q_DECL_NOTHROW;
diff --git a/src/corelib/tools/qelapsedtimer_generic.cpp b/src/corelib/tools/qelapsedtimer_generic.cpp
index 6324be00c0..7a52faa3c5 100644
--- a/src/corelib/tools/qelapsedtimer_generic.cpp
+++ b/src/corelib/tools/qelapsedtimer_generic.cpp
@@ -87,6 +87,8 @@ void QElapsedTimer::start() Q_DECL_NOTHROW
and then starting the timer again with start(), but it does so in one
single operation, avoiding the need to obtain the clock value twice.
+ Restarting the timer makes it valid again.
+
The following example illustrates how to use this function to calibrate a
parameter to a slow operation (for example, an iteration count) so that
this operation takes at least 250 milliseconds:
diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp
index 04269e485b..57cc863696 100644
--- a/src/corelib/tools/qrect.cpp
+++ b/src/corelib/tools/qrect.cpp
@@ -284,7 +284,7 @@ QT_BEGIN_NAMESPACE
Returns \c true if the rectangle is valid, otherwise returns \c false.
- A valid rectangle has a left() < right() and top() <
+ A valid rectangle has a left() <= right() and top() <=
bottom(). Note that non-trivial operations like intersections are
not defined for invalid rectangles. A valid rectangle is not empty
(i.e., isValid() == !isEmpty()).
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index f9fbc92d20..b3d7843506 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 12d9f9f14d..5a4460dea3 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -69,7 +69,7 @@ Q_GLOBAL_STATIC(QIconLoader, iconLoaderInstance)
static QString fallbackTheme()
{
if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
- const QVariant themeHint = theme->themeHint(QPlatformTheme::SystemIconThemeName);
+ const QVariant themeHint = theme->themeHint(QPlatformTheme::SystemIconFallbackThemeName);
if (themeHint.isValid())
return themeHint.toString();
}
@@ -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 c3b4b1444a..5de686c1ea 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 844bbb2eba..3e73462efc 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -232,7 +232,7 @@ public:
void setPixel(const QPoint &pt, uint index_or_rgb);
QVector<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 294bd90116..e30de3b6ac 100644
--- a/src/gui/kernel/qopenglwindow.h
+++ b/src/gui/kernel/qopenglwindow.h
@@ -42,6 +42,10 @@
#ifndef QOPENGLWINDOW_H
#define QOPENGLWINDOW_H
+#include <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 65bfc7f868..56e99ee8b8 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 de1de39db2..b9e7523aad 100644
--- a/src/gui/opengl/qopenglfunctions.h
+++ b/src/gui/opengl/qopenglfunctions.h
@@ -563,8 +563,10 @@ struct QOpenGLFunctionsPrivate
void (QOPENGLF_APIENTRYP VertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr);
// Special non-ES OpenGL variants, not to be called directly
+#ifndef QT_OPENGL_ES_2
void (QOPENGLF_APIENTRYP ClearDepth)(GLdouble depth);
void (QOPENGLF_APIENTRYP DepthRange)(GLdouble zNear, GLdouble zFar);
+#endif
};
// GLES2 + OpenGL1 common subset
diff --git a/src/gui/opengl/qopenglgradientcache.cpp b/src/gui/opengl/qopenglgradientcache.cpp
index 91b4d08474..f8060fc6a0 100644
--- a/src/gui/opengl/qopenglgradientcache.cpp
+++ b/src/gui/opengl/qopenglgradientcache.cpp
@@ -102,13 +102,13 @@ void QOpenGL2GradientCache::cleanCache()
GLuint QOpenGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity)
{
- QMutexLocker lock(&m_mutex);
quint64 hash_val = 0;
QGradientStops stops = gradient.stops();
for (int i = 0; i < stops.size() && i <= 2; i++)
hash_val += stops[i].second.rgba();
+ const QMutexLocker lock(&m_mutex);
QOpenGLGradientColorTableHash::const_iterator it = cache.constFind(hash_val);
if (it == cache.constEnd())
diff --git a/src/gui/opengl/qopenglvertexarrayobject.cpp b/src/gui/opengl/qopenglvertexarrayobject.cpp
index f39b10dc60..15f08ddfce 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 eb197378ad..549dce2923 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -3521,8 +3521,7 @@ static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule)
POINTBLOCK *tmpPtBlock;
int numFullPtBlocks = 0;
- if (!(region = new QRegionPrivate))
- return 0;
+ region = new QRegionPrivate;
/* special case a rectangle */
if (((Count == 4) ||
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index cb3cb34d27..0a22038bb4 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -132,6 +132,7 @@ static bool ft_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *leng
return result;
}
+static QFontEngineFT::Glyph emptyGlyph = {0, 0, 0, 0, 0, 0, 0, 0};
// -------------------------- Freetype support ------------------------------
@@ -858,6 +859,9 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
if (g && g->format == format && (fetchMetricsOnly || g->data))
return g;
+ if (!g && set && set->isGlyphMissing(glyph))
+ return &emptyGlyph;
+
QFontEngineFT::GlyphInfo info;
Q_ASSERT(format != Format_None);
@@ -894,8 +898,12 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
load_flags |= FT_LOAD_FORCE_AUTOHINT;
err = FT_Load_Glyph(face, glyph, load_flags);
}
- if (err != FT_Err_Ok)
+ if (err != FT_Err_Ok) {
qWarning("load glyph failed err=%x face=%p, glyph=%d", err, face, glyph);
+ if (set)
+ set->setGlyphMissing(glyph);
+ return &emptyGlyph;
+ }
FT_GlyphSlot slot = face->glyph;
@@ -1633,9 +1641,12 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlag
if (!face)
face = lockFace();
g = loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyphs->glyphs[i], 0, Format_None, true);
- glyphs->advances[i] = design ? QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10)
- : QFixed::fromFixed(face->glyph->metrics.horiAdvance).round();
- if (!cacheEnabled)
+ if (g)
+ glyphs->advances[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance);
+ else
+ glyphs->advances[i] = design ? QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10)
+ : QFixed::fromFixed(face->glyph->metrics.horiAdvance).round();
+ if (!cacheEnabled && g != &emptyGlyph)
delete g;
}
}
@@ -1674,7 +1685,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
xmax = qMax(xmax, x + g->width);
ymax = qMax(ymax, y + g->height);
overall.xoff += g->advance;
- if (!cacheEnabled)
+ if (!cacheEnabled && g != &emptyGlyph)
delete g;
} else {
int left = FLOOR(face->glyph->metrics.horiBearingX);
@@ -1717,7 +1728,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph)
overall.xoff = g->advance;
if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
overall.xoff = overall.xoff.round();
- if (!cacheEnabled)
+ if (!cacheEnabled && g != &emptyGlyph)
delete g;
} else {
int left = FLOOR(face->glyph->metrics.horiBearingX);
@@ -1808,7 +1819,7 @@ glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, QFixed subPixe
overall.width = g->width;
overall.height = g->height;
overall.xoff = g->advance;
- if (!glyphSet)
+ if (!glyphSet && g != &emptyGlyph)
delete g;
} else {
int left = FLOOR(face->glyph->metrics.horiBearingX);
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index 09c70c5083..e23024e472 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -187,8 +187,11 @@ public:
inline Glyph *getGlyph(glyph_t index, QFixed subPixelPosition = 0) const;
void setGlyph(glyph_t index, QFixed spp, Glyph *glyph);
+ inline bool isGlyphMissing(glyph_t index) const { return missing_glyphs.contains(index); }
+ inline void setGlyphMissing(glyph_t index) const { missing_glyphs.insert(index); }
private:
mutable QHash<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 17bc4fde98..2db8b3fc1b 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -2385,8 +2385,7 @@ bool QTextEngine::LayoutData::reallocate(int totalGlyphs)
return false;
}
- void **newMem = memory;
- newMem = (void **)::realloc(memory_on_stack ? 0 : memory, newAllocated*sizeof(void *));
+ void **newMem = (void **)::realloc(memory_on_stack ? 0 : memory, newAllocated*sizeof(void *));
if (!newMem) {
layoutState = LayoutFailed;
return false;
diff --git a/src/network/access/qnetworkreply_p.h b/src/network/access/qnetworkreply_p.h
index ad11ef3964..55d3d85592 100644
--- a/src/network/access/qnetworkreply_p.h
+++ b/src/network/access/qnetworkreply_p.h
@@ -65,6 +65,16 @@ QT_BEGIN_NAMESPACE
class QNetworkReplyPrivate: public QIODevicePrivate, public QNetworkHeadersPrivate
{
public:
+ enum State {
+ Idle, // The reply is idle.
+ Buffering, // The reply is buffering outgoing data.
+ Working, // The reply is uploading/downloading data.
+ Finished, // The reply has finished.
+ Aborted, // The reply has been aborted.
+ WaitingForSession, // The reply is waiting for the session to open before connecting.
+ Reconnecting // The reply will reconnect to once roaming has completed.
+ };
+
QNetworkReplyPrivate();
QNetworkRequest request;
QUrl url;
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index c5cf849a55..920dfdbb38 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -250,8 +250,8 @@ void QNetworkReplyHttpImpl::close()
{
Q_D(QNetworkReplyHttpImpl);
- if (d->state == QNetworkReplyHttpImplPrivate::Aborted ||
- d->state == QNetworkReplyHttpImplPrivate::Finished)
+ if (d->state == QNetworkReplyPrivate::Aborted ||
+ d->state == QNetworkReplyPrivate::Finished)
return;
// According to the documentation close only stops the download
@@ -268,23 +268,23 @@ void QNetworkReplyHttpImpl::abort()
{
Q_D(QNetworkReplyHttpImpl);
// FIXME
- if (d->state == QNetworkReplyHttpImplPrivate::Finished || d->state == QNetworkReplyHttpImplPrivate::Aborted)
+ if (d->state == QNetworkReplyPrivate::Finished || d->state == QNetworkReplyPrivate::Aborted)
return;
QNetworkReply::close();
- if (d->state != QNetworkReplyHttpImplPrivate::Finished) {
+ if (d->state != QNetworkReplyPrivate::Finished) {
// call finished which will emit signals
// FIXME shouldn't this be emitted Queued?
d->error(OperationCanceledError, tr("Operation canceled"));
// If state is WaitingForSession, calling finished has no effect
- if (d->state == QNetworkReplyHttpImplPrivate::WaitingForSession)
- d->state = QNetworkReplyHttpImplPrivate::Working;
+ if (d->state == QNetworkReplyPrivate::WaitingForSession)
+ d->state = QNetworkReplyPrivate::Working;
d->finished();
}
- d->state = QNetworkReplyHttpImplPrivate::Aborted;
+ d->state = QNetworkReplyPrivate::Aborted;
emit abortHttpRequest();
}
@@ -1800,13 +1800,13 @@ void QNetworkReplyHttpImplPrivate::_q_networkSessionConnected()
return;
switch (state) {
- case QNetworkReplyImplPrivate::Buffering:
- case QNetworkReplyImplPrivate::Working:
- case QNetworkReplyImplPrivate::Reconnecting:
+ case QNetworkReplyPrivate::Buffering:
+ case QNetworkReplyPrivate::Working:
+ case QNetworkReplyPrivate::Reconnecting:
// Migrate existing downloads to new network connection.
migrateBackend();
break;
- case QNetworkReplyImplPrivate::WaitingForSession:
+ case QNetworkReplyPrivate::WaitingForSession:
// Start waiting requests.
QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
break;
diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h
index 06a5383ae4..b7de947a29 100644
--- a/src/network/access/qnetworkreplyhttpimpl_p.h
+++ b/src/network/access/qnetworkreplyhttpimpl_p.h
@@ -160,16 +160,6 @@ public:
static QHttpNetworkRequest::Priority convert(const QNetworkRequest::Priority& prio);
- enum State {
- Idle, // The reply is idle.
- Buffering, // The reply is buffering outgoing data.
- Working, // The reply is uploading/downloading data.
- Finished, // The reply has finished.
- Aborted, // The reply has been aborted.
- WaitingForSession, // The reply is waiting for the session to open before connecting.
- Reconnecting // The reply will reconnect to once roaming has completed.
- };
-
QNetworkReplyHttpImplPrivate();
~QNetworkReplyHttpImplPrivate();
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index 616019ea41..be0ddf1388 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -301,13 +301,13 @@ void QNetworkReplyImplPrivate::_q_networkSessionConnected()
return;
switch (state) {
- case QNetworkReplyImplPrivate::Buffering:
- case QNetworkReplyImplPrivate::Working:
- case QNetworkReplyImplPrivate::Reconnecting:
+ case QNetworkReplyPrivate::Buffering:
+ case QNetworkReplyPrivate::Working:
+ case QNetworkReplyPrivate::Reconnecting:
// Migrate existing downloads to new network connection.
migrateBackend();
break;
- case QNetworkReplyImplPrivate::WaitingForSession:
+ case QNetworkReplyPrivate::WaitingForSession:
// Start waiting requests.
QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
break;
@@ -916,7 +916,7 @@ QNetworkReplyImpl::~QNetworkReplyImpl()
void QNetworkReplyImpl::abort()
{
Q_D(QNetworkReplyImpl);
- if (d->state == QNetworkReplyImplPrivate::Finished || d->state == QNetworkReplyImplPrivate::Aborted)
+ if (d->state == QNetworkReplyPrivate::Finished || d->state == QNetworkReplyPrivate::Aborted)
return;
// stop both upload and download
@@ -927,14 +927,14 @@ void QNetworkReplyImpl::abort()
QNetworkReply::close();
- if (d->state != QNetworkReplyImplPrivate::Finished) {
+ if (d->state != QNetworkReplyPrivate::Finished) {
// call finished which will emit signals
d->error(OperationCanceledError, tr("Operation canceled"));
- if (d->state == QNetworkReplyImplPrivate::WaitingForSession)
- d->state = QNetworkReplyImplPrivate::Working;
+ if (d->state == QNetworkReplyPrivate::WaitingForSession)
+ d->state = QNetworkReplyPrivate::Working;
d->finished();
}
- d->state = QNetworkReplyImplPrivate::Aborted;
+ d->state = QNetworkReplyPrivate::Aborted;
// finished may access the backend
if (d->backend) {
@@ -946,8 +946,8 @@ void QNetworkReplyImpl::abort()
void QNetworkReplyImpl::close()
{
Q_D(QNetworkReplyImpl);
- if (d->state == QNetworkReplyImplPrivate::Aborted ||
- d->state == QNetworkReplyImplPrivate::Finished)
+ if (d->state == QNetworkReplyPrivate::Aborted ||
+ d->state == QNetworkReplyPrivate::Finished)
return;
// stop the download
@@ -1041,7 +1041,7 @@ qint64 QNetworkReplyImpl::readData(char *data, qint64 maxlen)
if (d->downloadBuffer) {
qint64 maxAvail = qMin<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 9edc0f6b59..3340dcc91e 100644
--- a/src/network/access/qnetworkreplyimpl_p.h
+++ b/src/network/access/qnetworkreplyimpl_p.h
@@ -118,16 +118,6 @@ public:
NotifyCopyFinished
};
- enum State {
- Idle, // The reply is idle.
- Buffering, // The reply is buffering outgoing data.
- Working, // The reply is uploading/downloading data.
- Finished, // The reply has finished.
- Aborted, // The reply has been aborted.
- WaitingForSession, // The reply is waiting for the session to open before connecting.
- Reconnecting // The reply will reconnect to once roaming has completed.
- };
-
typedef QQueue<InternalNotifications> NotificationQueue;
QNetworkReplyImplPrivate();
diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp
index 2ea6d6e015..4825d223ee 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 d282a02827..f3f280d863 100644
--- a/src/network/ssl/qasn1element.cpp
+++ b/src/network/ssl/qasn1element.cpp
@@ -56,6 +56,14 @@ static OidNameMap createOidMap()
// used by unit tests
oids.insert(oids.end(), QByteArrayLiteral("0.9.2342.19200300.100.1.5"), QByteArrayLiteral("favouriteDrink"));
oids.insert(oids.end(), QByteArrayLiteral("1.2.840.113549.1.9.1"), QByteArrayLiteral("emailAddress"));
+ oids.insert(oids.end(), QByteArrayLiteral("1.3.6.1.5.5.7.1.1"), QByteArrayLiteral("authorityInfoAccess"));
+ oids.insert(oids.end(), QByteArrayLiteral("1.3.6.1.5.5.7.48.1"), QByteArrayLiteral("OCSP"));
+ oids.insert(oids.end(), QByteArrayLiteral("1.3.6.1.5.5.7.48.2"), QByteArrayLiteral("caIssuers"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.29.14"), QByteArrayLiteral("subjectKeyIdentifier"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.29.15"), QByteArrayLiteral("keyUsage"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.29.17"), QByteArrayLiteral("subjectAltName"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.29.19"), QByteArrayLiteral("basicConstraints"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.29.35"), QByteArrayLiteral("authorityKeyIdentifier"));
oids.insert(oids.end(), QByteArrayLiteral("2.5.4.10"), QByteArrayLiteral("O"));
oids.insert(oids.end(), QByteArrayLiteral("2.5.4.11"), QByteArrayLiteral("OU"));
oids.insert(oids.end(), QByteArrayLiteral("2.5.4.12"), QByteArrayLiteral("title"));
@@ -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 6b3179ac35..36a7c90de3 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 bae78f4347..47ea3343ea 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -122,7 +122,6 @@
#include "qsslcertificate.h"
#include "qsslcertificate_p.h"
-#include "qasn1element_p.h"
#include "qsslkey_p.h"
#include <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 472553c30c..b0c99e545d 100644
--- a/src/network/ssl/qsslcertificate_p.h
+++ b/src/network/ssl/qsslcertificate_p.h
@@ -109,13 +109,16 @@ public:
QSsl::KeyAlgorithm publicKeyAlgorithm;
QByteArray publicKeyDerData;
QMultiMap<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 391ee6f7f9..6ea78a408b 100644
--- a/src/network/ssl/qsslcertificate_qt.cpp
+++ b/src/network/ssl/qsslcertificate_qt.cpp
@@ -47,9 +47,17 @@
#include "qsslkey_p.h"
#include "qsslcertificateextension.h"
#include "qsslcertificateextension_p.h"
+#include "qasn1element_p.h"
QT_BEGIN_NAMESPACE
+enum GeneralNameType
+{
+ Rfc822NameType = 0x81,
+ DnsNameType = 0x82,
+ UniformResourceIdentifierType = 0x86
+};
+
bool QSslCertificate::operator==(const QSslCertificate &other) const
{
if (d == other.d)
@@ -150,8 +158,7 @@ QSslKey QSslCertificate::publicKey() const
QList<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 7e78ac0fee..6b0fa954eb 100644
--- a/src/network/ssl/qsslkey_openssl.cpp
+++ b/src/network/ssl/qsslkey_openssl.cpp
@@ -111,7 +111,8 @@ bool QSslKeyPrivate::fromEVP_PKEY(EVP_PKEY *pkey)
void QSslKeyPrivate::decodeDer(const QByteArray &der, bool deepClear)
{
- decodePem(pemFromDer(der), QByteArray(), deepClear);
+ QMap<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 2b0dab9933..b051ec6874 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 9c1476038a..d24606e6a6 100644
--- a/src/network/ssl/qsslkey_p.h
+++ b/src/network/ssl/qsslkey_p.h
@@ -91,8 +91,8 @@ public:
bool deepClear = true);
QByteArray pemHeader() const;
QByteArray pemFooter() const;
- QByteArray pemFromDer(const QByteArray &der) const;
- QByteArray derFromPem(const QByteArray &pem) const;
+ QByteArray pemFromDer(const QByteArray &der, const QMap<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 feeb7d6f87..bc1ebc3c08 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 2c83069694..c5b4146ee9 100644
--- a/src/network/ssl/qsslkey_winrt.cpp
+++ b/src/network/ssl/qsslkey_winrt.cpp
@@ -61,3 +61,101 @@ using namespace ABI::Windows::Security::Cryptography::Core;
using namespace ABI::Windows::Storage::Streams;
QT_USE_NAMESPACE
+
+struct SslKeyGlobal
+{
+ SslKeyGlobal()
+ {
+ HRESULT hr;
+ hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Security_Cryptography_Core_CryptographicEngine).Get(),
+ &engine);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<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 148c5d9b2f..dce8bd888c 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
@@ -249,6 +249,15 @@ void QEGLPlatformContext::adopt(const QVariant &nativeHandle, QPlatformOpenGLCon
void QEGLPlatformContext::updateFormatFromGL()
{
#ifndef QT_NO_OPENGL
+ // Have to save & restore to prevent QOpenGLContext::currentContext() from becoming
+ // inconsistent after QOpenGLContext::create().
+ EGLDisplay prevDisplay = eglGetCurrentDisplay();
+ if (prevDisplay == EGL_NO_DISPLAY) // when no context is current
+ prevDisplay = m_eglDisplay;
+ EGLContext prevContext = eglGetCurrentContext();
+ EGLSurface prevSurfaceDraw = eglGetCurrentSurface(EGL_DRAW);
+ EGLSurface prevSurfaceRead = eglGetCurrentSurface(EGL_READ);
+
// Make the context current to ensure the GL version query works. This needs a surface too.
const EGLint pbufferAttributes[] = {
EGL_WIDTH, 1,
@@ -300,7 +309,7 @@ void QEGLPlatformContext::updateFormatFromGL()
}
}
}
- eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglMakeCurrent(prevDisplay, prevSurfaceDraw, prevSurfaceRead, prevContext);
}
eglDestroySurface(m_eglDisplay, pbuffer);
#endif // QT_NO_OPENGL
diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor.cpp b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp
index b6293e60ec..7198d7c6fb 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcursor.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp
@@ -343,6 +343,8 @@ void QEGLPlatformCursor::draw(const QRectF &r)
{
if (!m_program) {
// one time initialization
+ initializeOpenGLFunctions();
+
createShaderPrograms();
if (!m_cursorAtlas.texture) {
@@ -387,6 +389,7 @@ void QEGLPlatformCursor::draw(const QRectF &r)
};
glBindTexture(GL_TEXTURE_2D, m_cursor.texture);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
m_program->enableAttributeArray(m_vertexCoordEntry);
m_program->enableAttributeArray(m_textureCoordEntry);
diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor_p.h b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h
index 6f4216874a..440bcc40eb 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcursor_p.h
+++ b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h
@@ -44,6 +44,7 @@
#include <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 26ae0eb724..75359fbaa3 100644
--- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp
+++ b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp
@@ -96,8 +96,9 @@ void QBasicFontDatabase::populateFontDatabase()
QString fontpath = fontDir();
if(!QFile::exists(fontpath)) {
- qFatal("QFontDatabase: Cannot find font directory %s - is Qt installed correctly?",
+ qWarning("QFontDatabase: Cannot find font directory %s - is Qt installed correctly?",
qPrintable(fontpath));
+ return;
}
QDir dir(fontpath);
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index de30fa825a..7b76177141 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -380,6 +380,9 @@ namespace QtAndroid
void setSurfaceGeometry(int surfaceId, const QRect &geometry)
{
+ if (surfaceId == -1)
+ return;
+
QJNIEnvironmentPrivate env;
if (!env)
return;
@@ -399,6 +402,9 @@ namespace QtAndroid
void destroySurface(int surfaceId)
{
+ if (surfaceId == -1)
+ return;
+
QMutexLocker lock(&m_surfacesMutex);
const auto &it = m_surfaces.find(surfaceId);
if (it != m_surfaces.end())
diff --git a/src/plugins/platforms/android/qandroideventdispatcher.cpp b/src/plugins/platforms/android/qandroideventdispatcher.cpp
index 074ba71f80..ab5070af9d 100644
--- a/src/plugins/platforms/android/qandroideventdispatcher.cpp
+++ b/src/plugins/platforms/android/qandroideventdispatcher.cpp
@@ -55,20 +55,26 @@ QAndroidEventDispatcher::~QAndroidEventDispatcher()
QAndroidEventDispatcherStopper::instance()->removeEventDispatcher(this);
}
+enum States {Running = 0, StopRequest = 1, Stopping = 2};
+
void QAndroidEventDispatcher::start()
{
- if (m_stopRequest.testAndSetAcquire(1, 0)) {
- m_dispatcherSemaphore.release();
+ int prevState = m_stopRequest.fetchAndStoreAcquire(Running);
+ if (prevState == Stopping) {
+ m_semaphore.release();
wakeUp();
+ } else if (prevState == Running) {
+ qWarning("Error: start without corresponding stop");
}
+ //else if prevState == StopRequest, no action needed
}
void QAndroidEventDispatcher::stop()
{
- if (m_stopRequest.testAndSetAcquire(0, 1)) {
+ if (m_stopRequest.testAndSetAcquire(Running, StopRequest))
wakeUp();
- m_stopperSemaphore.acquire();
- }
+ else
+ qWarning("Error: start/stop out of sync");
}
void QAndroidEventDispatcher::goingToStop(bool stop)
@@ -80,9 +86,8 @@ void QAndroidEventDispatcher::goingToStop(bool stop)
int QAndroidEventDispatcher::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timespec *timeout)
{
- if (m_stopRequest.load() == 1) {
- m_stopperSemaphore.release();
- m_dispatcherSemaphore.acquire();
+ if (m_stopRequest.testAndSetAcquire(StopRequest, Stopping)) {
+ m_semaphore.acquire();
wakeUp();
}
diff --git a/src/plugins/platforms/android/qandroideventdispatcher.h b/src/plugins/platforms/android/qandroideventdispatcher.h
index 8d1bcf2122..295763ce5b 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 5d47d2fda4..90eff615a2 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/qandroidinputcontext.cpp
@@ -45,6 +45,7 @@
#include "qandroidinputcontext.h"
#include "androidjnimain.h"
#include "androidjniinput.h"
+#include "qandroideventdispatcher.h"
#include <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 73c0a76dd7..d3fb22094a 100644
--- a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
@@ -44,6 +44,7 @@
#include "qandroidplatformscreen.h"
#include "androidjnimain.h"
+#include "qandroideventdispatcher.h"
#include <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 be013f027b..59b543e6d5 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp
@@ -49,6 +49,7 @@
#include "qwindowscontext.h"
+#include <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 f5f4923b2f..4bbe74b642 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp
@@ -53,8 +53,9 @@ QT_BEGIN_NAMESPACE
class QWindowsDirect2DPaintDevicePrivate
{
public:
- QWindowsDirect2DPaintDevicePrivate(QWindowsDirect2DBitmap *bitmap, QInternal::PaintDeviceFlags f)
- : engine(new QWindowsDirect2DPaintEngine(bitmap))
+ QWindowsDirect2DPaintDevicePrivate(QWindowsDirect2DBitmap *bitmap, QInternal::PaintDeviceFlags f,
+ QWindowsDirect2DPaintEngine::Flags paintFlags)
+ : engine(new QWindowsDirect2DPaintEngine(bitmap, paintFlags))
, bitmap(bitmap)
, flags(f)
{}
@@ -64,8 +65,9 @@ public:
QInternal::PaintDeviceFlags flags;
};
-QWindowsDirect2DPaintDevice::QWindowsDirect2DPaintDevice(QWindowsDirect2DBitmap *bitmap, QInternal::PaintDeviceFlags flags)
- : d_ptr(new QWindowsDirect2DPaintDevicePrivate(bitmap, flags))
+QWindowsDirect2DPaintDevice::QWindowsDirect2DPaintDevice(QWindowsDirect2DBitmap *bitmap, QInternal::PaintDeviceFlags flags,
+ QWindowsDirect2DPaintEngine::Flags paintFlags)
+ : d_ptr(new QWindowsDirect2DPaintDevicePrivate(bitmap, flags, paintFlags))
{
}
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h
index c9d8607497..33cc536b6d 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h
@@ -44,6 +44,7 @@
#include <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 f131419140..1d28befe41 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
@@ -233,9 +233,10 @@ class QWindowsDirect2DPaintEnginePrivate : public QPaintEngineExPrivate
{
Q_DECLARE_PUBLIC(QWindowsDirect2DPaintEngine)
public:
- QWindowsDirect2DPaintEnginePrivate(QWindowsDirect2DBitmap *bm)
+ QWindowsDirect2DPaintEnginePrivate(QWindowsDirect2DBitmap *bm, QWindowsDirect2DPaintEngine::Flags flags)
: bitmap(bm)
, clipFlags(0)
+ , flags(flags)
{
pen.reset();
brush.reset();
@@ -247,6 +248,7 @@ public:
unsigned int clipFlags;
QStack<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 1469d32876..4ed817b75f 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
@@ -59,7 +59,13 @@ class QWindowsDirect2DPaintEngine : public QPaintEngineEx
Q_DECLARE_PRIVATE(QWindowsDirect2DPaintEngine)
public:
- QWindowsDirect2DPaintEngine(QWindowsDirect2DBitmap *bitmap);
+ enum Flag {
+ NoFlag = 0,
+ UseGrayscaleAntialiasing = 1,
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ QWindowsDirect2DPaintEngine(QWindowsDirect2DBitmap *bitmap, Flags flags);
bool begin(QPaintDevice *pdev) Q_DECL_OVERRIDE;
bool end() Q_DECL_OVERRIDE;
@@ -119,6 +125,7 @@ private:
void adjustForAliasing(QRectF *rect);
void adjustForAliasing(QPointF *point);
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QWindowsDirect2DPaintEngine::Flags)
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp
index d9f7c595ca..88b440f857 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp
@@ -62,10 +62,11 @@ public:
, devicePixelRatio(1.0)
{}
- QWindowsDirect2DPlatformPixmapPrivate(QWindowsDirect2DBitmap *bitmap)
+ QWindowsDirect2DPlatformPixmapPrivate(QWindowsDirect2DBitmap *bitmap,
+ QWindowsDirect2DPaintEngine::Flags flags)
: owns_bitmap(false)
, bitmap(bitmap)
- , device(new QWindowsDirect2DPaintDevice(bitmap, QInternal::Pixmap))
+ , device(new QWindowsDirect2DPaintDevice(bitmap, QInternal::Pixmap, flags))
, devicePixelRatio(1.0)
{}
@@ -91,9 +92,10 @@ QWindowsDirect2DPlatformPixmap::QWindowsDirect2DPlatformPixmap(PixelType pixelTy
}
QWindowsDirect2DPlatformPixmap::QWindowsDirect2DPlatformPixmap(QPlatformPixmap::PixelType pixelType,
+ QWindowsDirect2DPaintEngine::Flags flags,
QWindowsDirect2DBitmap *bitmap)
: QPlatformPixmap(pixelType, Direct2DClass)
- , d_ptr(new QWindowsDirect2DPlatformPixmapPrivate(bitmap))
+ , d_ptr(new QWindowsDirect2DPlatformPixmapPrivate(bitmap, flags))
{
setSerialNumber(qt_d2dpixmap_serno++);
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
index 702ef7af92..69243abb1d 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
@@ -42,6 +42,7 @@
#ifndef QWINDOWSDIRECT2DPLATFORMPIXMAP_H
#define QWINDOWSDIRECT2DPLATFORMPIXMAP_H
+#include "qwindowsdirect2dpaintengine.h"
#include <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 15ec0c3526..f739493c1a 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 47c790da5d..6835c9cf6f 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h
@@ -56,9 +56,12 @@ public:
QWindowsDirect2DWindow(QWindow *window, const QWindowsWindowData &data);
~QWindowsDirect2DWindow();
+ void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE;
+
QPixmap *pixmap();
void flush(QWindowsDirect2DBitmap *bitmap, const QRegion &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 bc6e4d70e9..60a501f730 100644
--- a/src/plugins/platforms/directfb/qdirectfbblitter.cpp
+++ b/src/plugins/platforms/directfb/qdirectfbblitter.cpp
@@ -65,17 +65,22 @@ static QBlittable::Capabilities dfb_blitter_capabilities()
QDirectFbBlitter::QDirectFbBlitter(const QSize &rect, IDirectFBSurface *surface)
: QBlittable(rect, dfb_blitter_capabilities())
- , m_surface(surface)
+ , m_surface(surface)
+ , m_debugPaint(false)
{
m_surface->AddRef(m_surface.data());
DFBSurfaceCapabilities surfaceCaps;
m_surface->GetCapabilities(m_surface.data(), &surfaceCaps);
m_premult = (surfaceCaps & DSCAPS_PREMULTIPLIED);
+ if (qgetenv("QT_DIRECTFB_BLITTER_DEBUGPAINT").toInt())
+ m_debugPaint = true;
}
QDirectFbBlitter::QDirectFbBlitter(const QSize &rect, bool alpha)
- : QBlittable(rect, dfb_blitter_capabilities()), m_premult(false)
+ : QBlittable(rect, dfb_blitter_capabilities())
+ , m_premult(false)
+ , m_debugPaint(false)
{
DFBSurfaceDescription surfaceDesc;
memset(&surfaceDesc,0,sizeof(DFBSurfaceDescription));
@@ -95,6 +100,9 @@ QDirectFbBlitter::QDirectFbBlitter(const QSize &rect, bool alpha)
surfaceDesc.pixelformat = QDirectFbBlitter::pixmapFormat();
}
+ if (qgetenv("QT_DIRECTFB_BLITTER_DEBUGPAINT").toInt())
+ m_debugPaint = true;
+
IDirectFB *dfb = QDirectFbConvenience::dfbInterface();
dfb->CreateSurface(dfb , &surfaceDesc, m_surface.outPtr());
m_surface->Clear(m_surface.data(), 0, 0, 0, 0);
@@ -165,6 +173,8 @@ void QDirectFbBlitter::alphaFillRect(const QRectF &rect, const QColor &color, QP
result = m_surface->FillRectangle(m_surface.data(), x, y, w, h);
if (result != DFB_OK)
DirectFBError("QDirectFBBlitter::alphaFillRect()", result);
+ if (m_debugPaint)
+ drawDebugRect(QRect(x, y, w, h), QColor(Qt::blue));
}
void QDirectFbBlitter::drawPixmapOpacity(const QRectF &rect, const QPixmap &pixmap, const QRectF &subrect, QPainter::CompositionMode cmode, qreal opacity)
@@ -203,13 +213,19 @@ void QDirectFbBlitter::drawPixmapOpacity(const QRectF &rect, const QPixmap &pixm
if (cmode == QPainter::CompositionMode_SourceOver)
m_surface->SetDstBlendFunction(m_surface.data(), DSBF_INVSRCALPHA);
- if ((sRect.w == dRect.w) && (sRect.h == dRect.h))
+ if ((sRect.w == dRect.w) && (sRect.h == dRect.h)) {
result = m_surface->Blit(m_surface.data(), s, &sRect, dRect.x, dRect.y);
- else
+ if (result != DFB_OK)
+ DirectFBError("QDirectFBBlitter::drawPixmapOpacity()", result);
+ if (m_debugPaint)
+ drawDebugRect(QRect(dRect.x, dRect.y, sRect.w, sRect.h), QColor(Qt::green));
+ } else {
result = m_surface->StretchBlit(m_surface.data(), s, &sRect, &dRect);
-
- if (result != DFB_OK)
- DirectFBError("QDirectFBBlitter::drawPixmapExtended()", result);
+ if (result != DFB_OK)
+ DirectFBError("QDirectFBBlitter::drawPixmapOpacity()", result);
+ if (m_debugPaint)
+ drawDebugRect(QRect(dRect.x, dRect.y, dRect.w, dRect.h), QColor(Qt::red));
+ }
}
bool QDirectFbBlitter::drawCachedGlyphs(const QPaintEngineState *state, QFontEngine::GlyphFormat glyphFormat, int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions, QFontEngine *fontEngine)
@@ -287,6 +303,12 @@ bool QDirectFbBlitter::drawCachedGlyphs(const QPaintEngineState *state, QFontEng
m_surface->BatchBlit(m_surface.data(), cache->sourceSurface(), sourceRects.constData(), destPoints.constData(), nGlyphs);
+ if (m_debugPaint) {
+ for (int i = 0; i < nGlyphs; ++i) {
+ drawDebugRect(QRect(destPoints[i].x, destPoints[i].y, sourceRects[i].w, sourceRects[i].h), QColor(Qt::yellow));
+ }
+ }
+
if (rs->clip && rs->clip->enabled)
m_surface->SetClip(m_surface.data(), 0);
return true;
@@ -403,6 +425,41 @@ void QDirectFbBlitter::doUnlock()
m_surface->Unlock(m_surface.data());
}
+void QDirectFbBlitter::drawDebugRect(const QRect &rect, const QColor &color)
+{
+ int x, y, w, h;
+ DFBResult result;
+
+ // check parameters
+ rect.getRect(&x, &y ,&w, &h);
+ if ((w <= 0) || (h <= 0)) return;
+
+ m_surface->SetDrawingFlags(m_surface.data(),
+ DFBSurfaceDrawingFlags(m_premult ? (DSDRAW_BLEND | DSDRAW_SRC_PREMULTIPLY) : DSDRAW_BLEND));
+ m_surface->SetPorterDuff(m_surface.data(), DSPD_SRC_OVER);
+
+ // set color
+ m_surface->SetColor(m_surface.data(), color.red(), color.green(), color.blue(), 120);
+
+ result = m_surface->DrawLine(m_surface.data(), x, y, x + w-1, y);
+ if (result != DFB_OK)
+ DirectFBError("QDirectFBBlitter::drawDebugRect()", result);
+ result = m_surface->DrawLine(m_surface.data(), x + w-1, y, x + w-1, y + h-1);
+ if (result != DFB_OK)
+ DirectFBError("QDirectFBBlitter::drawDebugRect()", result);
+ result = m_surface->DrawLine(m_surface.data(), x + w-1, y + h-1, x, y + h-1);
+ if (result != DFB_OK)
+ DirectFBError("QDirectFBBlitter::drawDebugRect()", result);
+ result = m_surface->DrawLine(m_surface.data(), x, y + h-1, x, y);
+ if (result != DFB_OK)
+ DirectFBError("QDirectFBBlitter::drawDebugRect()", result);
+
+ m_surface->SetColor(m_surface.data(), color.red(), color.green(), color.blue(), 10);
+ result = m_surface->FillRectangle(m_surface.data(), x, y, w, h);
+ if (result != DFB_OK)
+ DirectFBError("QDirectFBBlitter::drawDebugRect()", result);
+}
+
void QDirectFbTextureGlyphCache::resizeTextureData(int width, int height)
{
m_surface.reset();;
diff --git a/src/plugins/platforms/directfb/qdirectfbblitter.h b/src/plugins/platforms/directfb/qdirectfbblitter.h
index c60f0fac25..4fa432462f 100644
--- a/src/plugins/platforms/directfb/qdirectfbblitter.h
+++ b/src/plugins/platforms/directfb/qdirectfbblitter.h
@@ -79,7 +79,10 @@ protected:
friend class QDirectFbConvenience;
private:
+ void drawDebugRect(const QRect &rect, const QColor &color);
+
bool m_premult;
+ bool m_debugPaint;
};
class QDirectFbBlitterPlatformPixmap : public QBlittablePlatformPixmap
diff --git a/src/plugins/platforms/eglfs/eglfs.pri b/src/plugins/platforms/eglfs/eglfs.pri
index 6e3ba54b97..6f463ba7d9 100644
--- a/src/plugins/platforms/eglfs/eglfs.pri
+++ b/src/plugins/platforms/eglfs/eglfs.pri
@@ -8,6 +8,11 @@ DEFINES += MESA_EGL_NO_X11_HEADERS
# EGLFS_PLATFORM_HOOKS_SOURCES += qeglfshooks_x11.cpp
# LIBS += -lX11 -lX11-xcb -lxcb
+# Uncomment these to enable the KMS hooks.
+# EGLFS_PLATFORM_HOOKS_SOURCES += qeglfshooks_kms.cpp
+# CONFIG += link_pkgconfig
+# PKGCONFIG += libdrm gbm
+
SOURCES += $$PWD/qeglfsintegration.cpp \
$$PWD/qeglfswindow.cpp \
$$PWD/qeglfsscreen.cpp \
diff --git a/src/plugins/platforms/eglfs/qeglfshooks_kms.cpp b/src/plugins/platforms/eglfs/qeglfshooks_kms.cpp
new file mode 100644
index 0000000000..9e5d624d87
--- /dev/null
+++ b/src/plugins/platforms/eglfs/qeglfshooks_kms.cpp
@@ -0,0 +1,422 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the qmake spec of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeglfshooks.h"
+#include <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 d770ea763a..82269d07c6 100644
--- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
@@ -120,13 +120,12 @@ QEGLPlatformContext *QEglFSIntegration::createContext(const QSurfaceFormat &form
QVariant *nativeHandle) const
{
QEglFSContext *ctx;
+ QSurfaceFormat adjustedFormat = QEglFSHooks::hooks()->surfaceFormatFor(format);
if (!nativeHandle || nativeHandle->isNull()) {
- EGLConfig config = QEglFSIntegration::chooseConfig(display, format);
- ctx = new QEglFSContext(QEglFSHooks::hooks()->surfaceFormatFor(format), shareContext, display,
- &config, QVariant());
+ EGLConfig config = QEglFSIntegration::chooseConfig(display, adjustedFormat);
+ ctx = new QEglFSContext(adjustedFormat, shareContext, display, &config, QVariant());
} else {
- ctx = new QEglFSContext(QEglFSHooks::hooks()->surfaceFormatFor(format), shareContext, display,
- 0, *nativeHandle);
+ ctx = new QEglFSContext(adjustedFormat, shareContext, display, 0, *nativeHandle);
}
*nativeHandle = QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(ctx->eglContext(), display));
return ctx;
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index d109d53168..064098157d 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -166,7 +166,7 @@
self.enabled = YES;
if (!m_duration) {
m_duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
- m_curve = UIViewAnimationCurve([[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue] << 16);
+ m_curve = UIViewAnimationCurve([[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue]);
}
m_context->scrollToCursor();
}
@@ -389,7 +389,7 @@ void QIOSInputContext::scroll(int y)
newBounds.origin.y = y;
QPointer<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 e876665431..f1184be1b4 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 bcff3e202c..e55def1992 100644
--- a/src/plugins/platforms/ios/qioswindow.h
+++ b/src/plugins/platforms/ios/qioswindow.h
@@ -73,6 +73,7 @@ public:
void setParent(const QPlatformWindow *window);
void handleContentOrientationChange(Qt::ScreenOrientation orientation);
void setVisible(bool visible);
+ void setOpacity(qreal level) Q_DECL_OVERRIDE;
bool isExposed() const Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm
index d8dd875d83..aa33a9b21d 100644
--- a/src/plugins/platforms/ios/qioswindow.mm
+++ b/src/plugins/platforms/ios/qioswindow.mm
@@ -74,6 +74,7 @@ QIOSWindow::QIOSWindow(QWindow *window)
screen()->availableGeometry().width(), screen()->availableGeometry().height());
setWindowState(window->windowState());
+ setOpacity(window->opacity());
}
QIOSWindow::~QIOSWindow()
@@ -135,6 +136,11 @@ void QIOSWindow::setVisible(bool visible)
}
}
+void QIOSWindow::setOpacity(qreal level)
+{
+ m_view.alpha = qBound(0.0, level, 1.0);
+}
+
void QIOSWindow::setGeometry(const QRect &rect)
{
m_normalGeometry = rect;
diff --git a/src/plugins/platforms/ios/quiview_textinput.mm b/src/plugins/platforms/ios/quiview_textinput.mm
index 2280b8259a..6b2707e706 100644
--- a/src/plugins/platforms/ios/quiview_textinput.mm
+++ b/src/plugins/platforms/ios/quiview_textinput.mm
@@ -49,19 +49,11 @@ class StaticVariables
public:
QInputMethodQueryEvent inputMethodQueryEvent;
bool inUpdateKeyboardLayout;
- QTextCharFormat markedTextFormat;
StaticVariables()
: inputMethodQueryEvent(Qt::ImQueryInput)
, inUpdateKeyboardLayout(false)
{
- // There seems to be no way to query how the preedit text
- // should be drawn. So we need to hard-code the color.
- QSysInfo::MacVersion iosVersion = QSysInfo::MacintoshVersion;
- if (iosVersion < QSysInfo::MV_IOS_7_0)
- markedTextFormat.setBackground(QColor(235, 239, 247));
- else
- markedTextFormat.setBackground(QColor(206, 221, 238));
}
};
@@ -301,8 +293,19 @@ Q_GLOBAL_STATIC(StaticVariables, staticVariables);
m_markedText = markedText ? QString::fromNSString(markedText) : QString();
+ static QTextCharFormat markedTextFormat;
+ if (markedTextFormat.isEmpty()) {
+ // There seems to be no way to query how the preedit text
+ // should be drawn. So we need to hard-code the color.
+ QSysInfo::MacVersion iosVersion = QSysInfo::MacintoshVersion;
+ if (iosVersion < QSysInfo::MV_IOS_7_0)
+ markedTextFormat.setBackground(QColor(235, 239, 247));
+ else
+ markedTextFormat.setBackground(QColor(206, 221, 238));
+ }
+
QList<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 a930aa6545..3368af046f 100644
--- a/src/plugins/platforms/kms/qkmsscreen.cpp
+++ b/src/plugins/platforms/kms/qkmsscreen.cpp
@@ -38,7 +38,6 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-//#include <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 1fa8dbb763..58237877a6 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 584efa1665..69f6f308b5 100644
--- a/src/plugins/platforms/platforms.pro
+++ b/src/plugins/platforms/platforms.pro
@@ -35,7 +35,7 @@ contains(QT_CONFIG, directfb) {
SUBDIRS += directfb
}
-contains(QT_CONFIG, kms) {
+contains(QT_CONFIG, kms):contains(QT_CONFIG, opengl) {
SUBDIRS += kms
}
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index c62875d0ef..8892fa6daa 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 6c4ac08da1..a7866516f0 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.h
+++ b/src/plugins/platforms/windows/qwindowseglcontext.h
@@ -53,6 +53,7 @@ struct QWindowsLibEGL
EGLint (EGLAPIENTRY * eglGetError)(void);
EGLDisplay (EGLAPIENTRY * eglGetDisplay)(EGLNativeDisplayType display_id);
+ EGLDisplay (EGLAPIENTRY * eglGetPlatformDisplayEXT)(EGLenum platform, void *native_display, const EGLint *attrib_list);
EGLBoolean (EGLAPIENTRY * eglInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor);
EGLBoolean (EGLAPIENTRY * eglTerminate)(EGLDisplay dpy);
EGLBoolean (EGLAPIENTRY * eglChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list,
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index e09018ef69..869df26ef6 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 2e677102a5..96c4a8bb78 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
@@ -384,7 +384,7 @@ bool QWindowsMouseHandler::translateMouseWheelEvent(QWindow *window, HWND,
// 2) The window receiving the event
// If a window is blocked by modality, it can't get the event.
const QPoint globalPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
- QWindow *receiver = QWindowsScreen::windowAt(globalPos);
+ QWindow *receiver = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE);
bool handleEvent = true;
if (!isValidWheelReceiver(receiver)) {
receiver = window;
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index a5a291a8d8..f491b51aa8 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 49581db41a..44638bcbe0 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -104,12 +104,8 @@ public:
QString name() const Q_DECL_OVERRIDE { return m_data.name; }
Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE { return m_data.orientation; }
QList<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 7d020ff9d6..b6940e6850 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
@@ -47,6 +47,7 @@
#include "qwindowscontext.h"
#include "qwindowskeymapper.h"
#include "qwindowswindow.h"
+#include "qwindowsscreen.h"
#include <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 e6b996c685..672d169984 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -2083,26 +2083,6 @@ void QWindowsWindow::setCursor(const QWindowsWindowCursor &c)
#endif
}
-/*!
- \brief Find a child window using flags from ChildWindowFromPointEx.
-*/
-
-QWindowsWindow *QWindowsWindow::childAtScreenPoint(const QPoint &screenPoint,
- unsigned cwexflags) const
-{
- if (m_data.hwnd)
- return QWindowsContext::instance()->findPlatformWindowAt(m_data.hwnd, screenPoint, cwexflags);
- return 0;
-}
-
-QWindowsWindow *QWindowsWindow::childAt(const QPoint &clientPoint, unsigned cwexflags) const
-{
- if (m_data.hwnd)
- return childAtScreenPoint(QWindowsGeometryHint::mapToGlobal(m_data.hwnd, clientPoint),
- cwexflags);
- return 0;
-}
-
#ifndef Q_OS_WINCE
void QWindowsWindow::setAlertState(bool enabled)
{
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index cb9da6fe27..03c71351bd 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -246,11 +246,6 @@ public:
void setCursor(const QWindowsWindowCursor &c);
void applyCursor();
- QWindowsWindow *childAt(const QPoint &clientPoint,
- unsigned cwexflags = CWP_SKIPINVISIBLE) const;
- QWindowsWindow *childAtScreenPoint(const QPoint &screenPoint,
- unsigned cwexflags = CWP_SKIPINVISIBLE) const;
-
static QByteArray debugWindowFlags(Qt::WindowFlags wf);
inline bool testFlag(unsigned f) const { return (m_flags & f) != 0; }
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index 6c905735dd..b981b94748 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -828,12 +828,14 @@ HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *, ICharacterReceivedEvent
HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *, IPointerEventArgs *args)
{
+ Q_D(QWinRTScreen);
+
ComPtr<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 d6fe5f3477..3b13df863e 100644
--- a/src/plugins/platforms/xcb/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/qglxintegration.cpp
@@ -323,11 +323,11 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
// Query the OpenGL version and profile
if (m_context && window) {
+ GLXContext prevContext = glXGetCurrentContext();
+ GLXDrawable prevDrawable = glXGetCurrentDrawable();
glXMakeCurrent(DISPLAY_FROM_XCB(screen), window, m_context);
updateFormatFromContext(m_format);
-
- // Make our context non-current
- glXMakeCurrent(DISPLAY_FROM_XCB(screen), 0, 0);
+ glXMakeCurrent(DISPLAY_FROM_XCB(screen), prevDrawable, prevContext);
}
// Destroy our temporary window
@@ -419,6 +419,8 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const
}
// Update OpenGL version and buffer sizes in our format.
+ GLXContext prevContext = glXGetCurrentContext();
+ GLXDrawable prevDrawable = glXGetCurrentDrawable();
if (!glXMakeCurrent(dpy, window, context)) {
qWarning("QGLXContext: Failed to make provided context current");
return;
@@ -431,7 +433,7 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const
qglx_surfaceFormatFromVisualInfo(&m_format, dpy, vinfo);
else
qglx_surfaceFormatFromGLXFBConfig(&m_format, dpy, config);
- glXMakeCurrent(dpy, 0, 0);
+ glXMakeCurrent(dpy, prevDrawable, prevContext);
XDestroyWindow(dpy, window);
if (vinfo)
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 84d00d0e09..60a36a8da1 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -413,7 +413,7 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
#if defined(XCB_USE_XINPUT21) || !defined(QT_NO_TABLETEVENT)
static qreal fixed1616ToReal(FP1616 val)
{
- return (qreal(val >> 16)) + (val & 0xFF) / (qreal)0xFF;
+ return (qreal(val >> 16)) + (val & 0xFFFF) / (qreal)0xFFFF;
}
#endif // defined(XCB_USE_XINPUT21) || !defined(QT_NO_TABLETEVENT)
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index fa5ccf58ef..e3fae73fd3 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -406,7 +406,7 @@ void QXcbDrag::move(const QMouseEvent *me)
int target_version = 1;
if (proxy_target) {
- xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, target,
+ xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, proxy_target,
atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 1);
xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0);
if (!reply || reply->type == XCB_NONE)
diff --git a/src/src.pro b/src/src.pro
index 13f62137ec..ab93641131 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -85,7 +85,6 @@ src_3rdparty_harfbuzzng.target = sub-3rdparty-harfbuzzng
src_angle.subdir = $$PWD/angle
src_angle.target = sub-angle
-angle_d3d11: src_angle.depends = src_corelib
src_gui.subdir = $$PWD/gui
src_gui.target = sub-gui
diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp
index ae8206b8c3..243c8090db 100644
--- a/src/tools/qdoc/htmlgenerator.cpp
+++ b/src/tools/qdoc/htmlgenerator.cpp
@@ -996,10 +996,16 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
break;
case Atom::SectionRight:
break;
- case Atom::SectionHeadingLeft:
- out() << "<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 f47980d786..82c3675508 100644
--- a/src/widgets/accessible/qaccessiblemenu.cpp
+++ b/src/widgets/accessible/qaccessiblemenu.cpp
@@ -294,8 +294,7 @@ QString QAccessibleMenuItem::text(QAccessible::Text t) const
QString str;
switch (t) {
case QAccessible::Name:
- str = m_action->text();
- str = qt_accStripAmp(str);
+ str = qt_accStripAmp(m_action->text());
break;
case QAccessible::Accelerator: {
#ifndef QT_NO_SHORTCUT
diff --git a/src/widgets/accessible/qaccessiblewidgets.cpp b/src/widgets/accessible/qaccessiblewidgets.cpp
index cc6310d591..b28f05cf8e 100644
--- a/src/widgets/accessible/qaccessiblewidgets.cpp
+++ b/src/widgets/accessible/qaccessiblewidgets.cpp
@@ -73,6 +73,7 @@
QT_BEGIN_NAMESPACE
QString qt_accStripAmp(const QString &text);
+QString qt_accHotKey(const QString &text);
QList<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 e8827f4537..d5933a6804 100644
--- a/src/widgets/accessible/simplewidgets.cpp
+++ b/src/widgets/accessible/simplewidgets.cpp
@@ -121,14 +121,14 @@ QString QAccessibleButton::text(QAccessible::Text t) const
case QAccessible::Name:
str = widget()->accessibleName();
if (str.isEmpty())
- str = button()->text();
+ str = qt_accStripAmp(button()->text());
break;
default:
break;
}
if (str.isEmpty())
str = QAccessibleWidget::text(t);
- return qt_accStripAmp(str);
+ return str;
}
QAccessible::State QAccessibleButton::state() const
@@ -395,6 +395,8 @@ QString QAccessibleDisplay::text(QAccessible::Text t) const
doc.setHtml(str);
str = doc.toPlainText();
}
+ if (label->buddy())
+ str = qt_accStripAmp(str);
#ifndef QT_NO_LCDNUMBER
} else if (qobject_cast<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 4d1835f178..7e3a01ef8b 100644
--- a/src/widgets/graphicsview/qgraphicsitem_p.h
+++ b/src/widgets/graphicsview/qgraphicsitem_p.h
@@ -318,7 +318,7 @@ public:
virtual void resolvePalette(uint inheritedMask)
{
for (int i = 0; i < children.size(); ++i)
- children.at(i)->d_ptr->resolveFont(inheritedMask);
+ children.at(i)->d_ptr->resolvePalette(inheritedMask);
}
virtual bool isProxyWidget() const;
diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp
index 1cd162e6bb..df74352e2b 100644
--- a/src/widgets/graphicsview/qgraphicsscene.cpp
+++ b/src/widgets/graphicsview/qgraphicsscene.cpp
@@ -1608,9 +1608,9 @@ void QGraphicsScenePrivate::updatePalette(const QPalette &palette)
// whose parent is not a widget.
foreach (QGraphicsItem *item, q->items()) {
if (!item->parentItem()) {
- // Resolvefont for an item is a noop operation, but
+ // ResolvePalette for an item is a noop operation, but
// every item can be a widget, or can have a widget
- // childre.
+ // children.
item->d_ptr->resolvePalette(palette.resolve());
}
}
diff --git a/src/widgets/graphicsview/qgraphicsscene.h b/src/widgets/graphicsview/qgraphicsscene.h
index d95237baef..ba47d45d63 100644
--- a/src/widgets/graphicsview/qgraphicsscene.h
+++ b/src/widgets/graphicsview/qgraphicsscene.h
@@ -313,7 +313,6 @@ private:
friend class QGraphicsEffect;
friend class QGraphicsSceneIndex;
friend class QGraphicsSceneIndexPrivate;
- friend class QGraphicsSceneLinearIndex;
friend class QGraphicsSceneBspTreeIndex;
friend class QGraphicsSceneBspTreeIndexPrivate;
friend class QGraphicsItemEffectSourcePrivate;
diff --git a/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h b/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h
index baf3de3755..5788818394 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 f438f60e47..3486396f54 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -3563,7 +3563,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
for (int i = 0; i < touchEvent->_touchPoints.size(); ++i) {
QTouchEvent::TouchPoint &pt = touchEvent->_touchPoints[i];
QRectF rect = pt.rect();
- rect.moveCenter(offset);
+ rect.translate(offset);
pt.d->rect = rect;
pt.d->startPos = pt.startPos() + offset;
pt.d->lastPos = pt.lastPos() + offset;
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index d8f31bfcc8..3dae22cdc7 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 28d802e1f4..f706ea7567 100644
--- a/src/widgets/kernel/qopenglwidget.h
+++ b/src/widgets/kernel/qopenglwidget.h
@@ -42,6 +42,10 @@
#ifndef QOPENGLWIDGET_H
#define QOPENGLWIDGET_H
+#include <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 e57c3285d2..48c2ad9e47 100644
--- a/src/widgets/kernel/qstandardgestures.cpp
+++ b/src/widgets/kernel/qstandardgestures.cpp
@@ -335,7 +335,7 @@ QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state,
d->swipeAngle = QLineF(p1.startScreenPos(), p1.screenPos()).angle();
static const int MoveThreshold = 50;
- if (xDistance > MoveThreshold || yDistance > MoveThreshold) {
+ if (qAbs(xDistance) > MoveThreshold || qAbs(yDistance) > MoveThreshold) {
// measure the distance to check if the direction changed
d->lastPositions[0] = p1.screenPos().toPoint();
d->lastPositions[1] = p2.screenPos().toPoint();
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 34adea866e..65978ef562 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 2a968939e4..103e244593 100644
--- a/src/widgets/kernel/qwidgetbackingstore.cpp
+++ b/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -1158,6 +1158,7 @@ void QWidgetBackingStore::doSync()
return;
}
+#ifndef QT_NO_OPENGL
// There is something other dirty than the renderToTexture widgets.
// Now it is time to include the renderToTexture ones among the others.
if (widgetTextures && widgetTextures->count()) {
@@ -1167,6 +1168,8 @@ void QWidgetBackingStore::doSync()
toClean += rect;
}
}
+#endif
+
// The dirtyRenderToTextureWidgets list is useless here, so just reset. As
// unintuitive as it is, we need to send paint events to renderToTexture
// widgets always when something (any widget) needs to be updated, even if
@@ -1249,8 +1252,10 @@ void QWidgetBackingStore::flush(QWidget *widget)
QWidget *target = widget ? widget : tlw;
qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset, widgetTextures, this);
dirtyOnScreen = QRegion();
+#ifndef QT_NO_OPENGL
if (widgetTextures && widgetTextures->count())
return;
+#endif
}
if (!dirtyOnScreenWidgets || dirtyOnScreenWidgets->isEmpty()) {
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index cc24c79c09..ce6d3d708f 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 9ab8f8f08a..2f04a20cd0 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 872b6f0e9e..93994abf6d 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 e3699da7ef..8b79a68f61 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 f2f208fbb5..9f54ec8f21 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 e694eb4e7e..8dc3c6cb48 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 7327fa5581..6e1cfe6db5 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 235cbc7865..abbba87039 100644
--- a/src/widgets/util/qscroller.cpp
+++ b/src/widgets/util/qscroller.cpp
@@ -746,9 +746,8 @@ void QScroller::ensureVisible(const QRectF &rect, qreal xmargin, qreal ymargin,
return;
// -- calculate the current pos (or the position after the current scroll)
- QPointF startPos = d->contentPosition + d->overshootPosition;
- startPos = QPointF(d->scrollingSegmentsEndPos(Qt::Horizontal),
- d->scrollingSegmentsEndPos(Qt::Vertical));
+ QPointF startPos(d->scrollingSegmentsEndPos(Qt::Horizontal),
+ d->scrollingSegmentsEndPos(Qt::Vertical));
QRectF marginRect(rect.x() - xmargin, rect.y() - ymargin,
rect.width() + 2 * xmargin, rect.height() + 2 * ymargin);
diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp
index 1b48441993..0e78c1493b 100644
--- a/src/widgets/widgets/qabstractscrollarea.cpp
+++ b/src/widgets/widgets/qabstractscrollarea.cpp
@@ -1191,10 +1191,12 @@ bool QAbstractScrollArea::viewportEvent(QEvent *e)
case QEvent::DragMove:
case QEvent::DragLeave:
#endif
+#ifndef QT_NO_OPENGL
// QOpenGLWidget needs special support because it has to know
// its size has changed, so that it can resize its fbo.
if (e->type() == QEvent::Resize)
QWidgetPrivate::get(viewport())->resizeViewportFramebuffer();
+#endif
return QFrame::event(e);
case QEvent::LayoutRequest:
#ifndef QT_NO_GESTURES
diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp
index 2eb04d146e..213e72183f 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 7ad893a54e..58ec068bb2 100644
--- a/src/widgets/widgets/qlineedit_p.cpp
+++ b/src/widgets/widgets/qlineedit_p.cpp
@@ -324,7 +324,7 @@ void QLineEditIconButton::paintEvent(QPaintEvent *)
state = isDown() ? QIcon::Selected : QIcon::Normal;
const QPixmap iconPixmap = icon().pixmap(QSize(IconButtonSize, IconButtonSize),
state, QIcon::Off);
- QRect pixmapRect = QRect(0, 0, iconPixmap.width(), iconPixmap.height());
+ QRect pixmapRect = QRect(QPoint(0, 0), iconPixmap.size() / iconPixmap.devicePixelRatio());
pixmapRect.moveCenter(rect().center());
painter.setOpacity(m_opacity);
painter.drawPixmap(pixmapRect, iconPixmap);
diff --git a/src/widgets/widgets/qmdisubwindow.cpp b/src/widgets/widgets/qmdisubwindow.cpp
index 5521d866b2..5166c3cf38 100644
--- a/src/widgets/widgets/qmdisubwindow.cpp
+++ b/src/widgets/widgets/qmdisubwindow.cpp
@@ -1043,6 +1043,7 @@ void QMdiSubWindowPrivate::createSystemMenu()
Q_ASSERT_X(q, "QMdiSubWindowPrivate::createSystemMenu",
"You can NOT call this function before QMdiSubWindow's ctor");
systemMenu = new QMenu(q);
+ systemMenu->installEventFilter(q);
const QStyle *style = q->style();
addToSystemMenu(RestoreAction, QMdiSubWindow::tr("&Restore"), SLOT(showNormal()));
actions[RestoreAction]->setIcon(style->standardIcon(QStyle::SP_TitleBarNormalButton, 0, q));
@@ -2569,7 +2570,6 @@ void QMdiSubWindow::showSystemMenu()
// Adjust x() with -menuwidth in reverse mode.
if (isRightToLeft())
globalPopupPos -= QPoint(d->systemMenu->sizeHint().width(), 0);
- d->systemMenu->installEventFilter(this);
d->systemMenu->popup(globalPopupPos);
}
#endif // QT_NO_MENU
@@ -2702,7 +2702,6 @@ bool QMdiSubWindow::eventFilter(QObject *object, QEvent *event)
QMouseEvent *mouseEvent = static_cast<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 df13085dee..3f34a08b5e 100644
--- a/src/widgets/widgets/qplaintextedit.cpp
+++ b/src/widgets/widgets/qplaintextedit.cpp
@@ -690,10 +690,9 @@ void QPlainTextEditPrivate::ensureVisible(int position, bool center, bool forceC
QRectF br = control->blockBoundingRect(block);
if (!br.isValid())
return;
- QRectF lr = br;
QTextLine line = block.layout()->lineForTextPosition(position - block.position());
Q_ASSERT(line.isValid());
- lr = line.naturalTextRect().translated(br.topLeft());
+ QRectF lr = line.naturalTextRect().translated(br.topLeft());
if (lr.bottom() >= visible.bottom() || (center && lr.top() < visible.top()) || forceCenter){
diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
index 0389ae7976..076e3eee1c 100644
--- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
+++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
@@ -45,6 +45,8 @@
#include <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 f2852f6a50..48e3745be4 100644
--- a/tests/auto/corelib/tools/qelapsedtimer/tst_qelapsedtimer.cpp
+++ b/tests/auto/corelib/tools/qelapsedtimer/tst_qelapsedtimer.cpp
@@ -48,12 +48,7 @@ static const int minResolution = 50; // the minimum resolution for the tests
QDebug operator<<(QDebug s, const QElapsedTimer &t)
{
- union {
- QElapsedTimer t;
- struct { qint64 t1, t2; } i;
- } copy;
- copy.t = t;
- s.nospace() << "(" << copy.i.t1 << ", " << copy.i.t2 << ")";
+ s.nospace() << "(" << t.msecsSinceReference() << ")";
return s.space();
}
@@ -81,8 +76,7 @@ void tst_QElapsedTimer::validity()
{
QElapsedTimer t;
- t.invalidate();
- QVERIFY(!t.isValid());
+ QVERIFY(!t.isValid()); // non-POD now, it should always start invalid
t.start();
QVERIFY(t.isValid());
diff --git a/tests/auto/gui/kernel/qwindow/qwindow.pro b/tests/auto/gui/kernel/qwindow/qwindow.pro
index e419a10440..5210585796 100644
--- a/tests/auto/gui/kernel/qwindow/qwindow.pro
+++ b/tests/auto/gui/kernel/qwindow/qwindow.pro
@@ -4,3 +4,5 @@ TARGET = tst_qwindow
QT += core-private gui-private testlib
SOURCES += tst_qwindow.cpp
+
+contains(QT_CONFIG,dynamicgl):win32:!wince*:!winrt: LIBS += -luser32
diff --git a/tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp b/tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp
index 661d13bc69..92b603473b 100644
--- a/tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp
+++ b/tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp
@@ -49,6 +49,10 @@ class tst_QAsn1Element : public QObject
private slots:
void emptyConstructor();
+ void equals_data();
+ void equals();
+ void toBool_data();
+ void toBool();
void dateTime_data();
void dateTime();
void integer_data();
@@ -68,6 +72,62 @@ void tst_QAsn1Element::emptyConstructor()
QCOMPARE(elem.value(), QByteArray());
}
+Q_DECLARE_METATYPE(QAsn1Element)
+
+void tst_QAsn1Element::equals_data()
+{
+ QTest::addColumn<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 cc90be00a2..229ce4abb5 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 78cfb9ce92..4ec4f27e6f 100644
--- a/tests/auto/network/ssl/qsslkey/qsslkey.pro
+++ b/tests/auto/network/ssl/qsslkey/qsslkey.pro
@@ -4,6 +4,9 @@ CONFIG += parallel_test
SOURCES += tst_qsslkey.cpp
!wince*:win32:LIBS += -lws2_32
QT = core network testlib
+contains(QT_CONFIG, private_tests) {
+ QT += core-private network-private
+}
TARGET = tst_qsslkey
diff --git a/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-rc2.pem b/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-rc2.pem
new file mode 100644
index 0000000000..7a0722fb8d
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-rc2.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-CBC,EAAF396E2CDD3680
+
+G+kY27Vq0Bkw6dEGlpe4oyyXlilyKJgkX53NQHv0WtLsu+cfamGst9viSQbAluP0
+Pk2m78Z05IZHBkxcl20tZZR3G3hFTVqf7OemEucT5Kb/Vx6V++ZXY5eI54bh1oEJ
+f8klr2DnscyTYdT33cmMuaxUm1sWjHeBBdQuQlMnW11XoCiGQMgMyf2fwbzd/og+
+vDPtORIMw+zedxaTsiOyNASLWB5ILDpUR9PTzz1tRIIOF5DnKttEe3SYPIqkLhxu
+N7OtpVhor0QUulph8sS2uiilTVyaYVciOJK7Cqq2K015l9nlqGg/KI0GRIC9ty+k
+wd+/Hdazp+YcLn3tL8jhekST/DAxK9VIb0DBvaboKr8UJw35nLOwA7smsij50l2S
+kfpu9z/80gFbnSSQo7L8zD/kBzaPlup0H+h96rF3IjdCrnbveHlvJDo3GcPNxauw
+rGUQXnnMzDVSTY179HfcgLZdsm3uOIBicEFaxXu2/L4Eof9yp8D/b6SeZeS41O7a
+ICvLXxkiIfQHukHvqMLJ2SqKQ0J8zEXN0OBSLjaHUkBIOs3L4IFe2v8DMN798GrG
+QzcxC0bmr9s6TvihlYFBbYkMZ3IYPT4SFZg92/pKTPlyD/Blc9oZm8QpQMGIMDKc
+nWDLeqeCTXV6TL1mymqzwyzs9+4cXvEiM167FsLqk5tGRIyl4AR/dItELEtCWl3I
+koIOUEk5rbJekOhTc85SFSQmCV0IebsUv0CpdWlmNeexNryLZu0r6kTUFWzpHcv/
+0yEaBQFLVx9QAfRSIiNt+yAgGnpMxxMxeHs6shVmuscZ0fV50GpOpA==
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
index 642b115bee..1c16f47ad6 100644
--- a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
+++ b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
@@ -47,6 +47,11 @@
#include <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 33cee37b92..295b60e739 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 745c8f2499..bd3997f8c9 100644
--- a/tests/auto/other/other.pro
+++ b/tests/auto/other/other.pro
@@ -3,7 +3,6 @@ SUBDIRS=\
# atwrapper \ # QTBUG-19452
baselineexample \
compiler \
- d3dcompiler \
gestures \
headersclean \
lancelot \
@@ -58,8 +57,6 @@ cross_compile: SUBDIRS -= \
wince*|!contains(QT_CONFIG, accessibility): SUBDIRS -= qaccessibility
-!angle_d3d11: SUBDIRS -= d3dcompiler
-
!contains(QT_CONFIG, accessibility-atspi-bridge): SUBDIRS -= qaccessibilitylinux
!mac: SUBDIRS -= \
diff --git a/tests/auto/other/qaccessibility/accessiblewidgets.h b/tests/auto/other/qaccessibility/accessiblewidgets.h
new file mode 100644
index 0000000000..c15cd43f85
--- /dev/null
+++ b/tests/auto/other/qaccessibility/accessiblewidgets.h
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef ACCESSIBLEWIDGETS_H
+#define ACCESSIBLEWIDGETS_H
+
+#include <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 e6c5bb1149..8d445437df 100644
--- a/tests/auto/other/qaccessibility/qaccessibility.pro
+++ b/tests/auto/other/qaccessibility/qaccessibility.pro
@@ -2,7 +2,8 @@ CONFIG += testcase
TARGET = tst_qaccessibility
requires(contains(QT_CONFIG,accessibility))
QT += testlib core-private gui-private widgets-private
-SOURCES += tst_qaccessibility.cpp
+SOURCES += tst_qaccessibility.cpp
+HEADERS += accessiblewidgets.h
unix:!mac:LIBS+=-lm
diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
index d3c9aa87ef..68723e9c2f 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 c89b05616d..8847a5748f 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -461,6 +461,7 @@ private slots:
void touchEventPropagation_data();
void touchEventPropagation();
void deviceCoordinateCache_simpleRotations();
+ void resolvePaletteForItemChildren();
// task specific tests below me
void task141694_textItemEnsureVisible();
@@ -11695,5 +11696,21 @@ void tst_QGraphicsItem::QTBUG_21618_untransformable_sceneTransform()
QCOMPARE(item2_bottomright->deviceTransform(tx).map(QPointF()), QPointF(100, 300));
}
+void tst_QGraphicsItem::resolvePaletteForItemChildren()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem item(0, 0, 50, -150);
+ scene.addItem(&item);
+ QGraphicsWidget widget;
+ widget.setParentItem(&item);
+
+ QColor green(Qt::green);
+ QPalette paletteForScene = scene.palette();
+ paletteForScene.setColor(QPalette::Active, QPalette::Window, green);
+ scene.setPalette(paletteForScene);
+
+ QCOMPARE(widget.palette().color(QPalette::Active, QPalette::Window), green);
+}
+
QTEST_MAIN(tst_QGraphicsItem)
#include "tst_qgraphicsitem.moc"
diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp
index 3471ed78ae..ddfb1d955b 100644
--- a/tools/configure/configureapp.cpp
+++ b/tools/configure/configureapp.cpp
@@ -566,9 +566,6 @@ void Configure::parseCmdLine()
else if (configCmdLine.at(i) == "-angle") {
dictionary[ "ANGLE" ] = "yes";
dictionary[ "ANGLE_FROM" ] = "commandline";
- } else if (configCmdLine.at(i) == "-angle-d3d11") {
- dictionary[ "ANGLE" ] = "d3d11";
- dictionary[ "ANGLE_FROM" ] = "commandline";
} else if (configCmdLine.at(i) == "-no-angle") {
dictionary[ "ANGLE" ] = "no";
dictionary[ "ANGLE_FROM" ] = "commandline";
@@ -1640,7 +1637,7 @@ void Configure::applySpecSpecifics()
dictionary[ "ICU" ] = "qt";
dictionary[ "CE_CRT" ] = "yes";
dictionary[ "LARGE_FILE" ] = "no";
- dictionary[ "ANGLE" ] = "d3d11";
+ dictionary[ "ANGLE" ] = "yes";
dictionary[ "DYNAMICGL" ] = "no";
} else if (dictionary.value("XQMAKESPEC").startsWith("wince")) {
dictionary[ "STYLE_WINDOWSXP" ] = "no";
@@ -1931,7 +1928,6 @@ bool Configure::displayHelp()
}
desc("ANGLE", "yes", "-angle", "Use the ANGLE implementation of OpenGL ES 2.0.");
- desc("ANGLE", "d3d11", "-angle-d3d11", "Use the Direct3D 11-based ANGLE implementation of OpenGL ES 2.0.");
desc("ANGLE", "no", "-no-angle", "Do not use ANGLE.\nSee http://code.google.com/p/angleproject/\n");
// Qt\Windows only options go below here --------------------------------------------------------------------------------
desc("\nQt for Windows only:\n\n");
@@ -2124,7 +2120,7 @@ bool Configure::checkAngleAvailability(QString *errorMessage /* = 0 */) const
}
}
- const QString directXLibrary = dictionary["ANGLE"] == "d3d11" ? QStringLiteral("d3d11.lib") : QStringLiteral("d3d9.lib");
+ const QString directXLibrary = QStringLiteral("d3d11.lib"); // Ensures at least the June 2010 DXSDK is present
if (!findFile(directXLibrary)) {
if (errorMessage)
*errorMessage = QString::fromLatin1("The library '%1' could not be found.").arg(directXLibrary);
@@ -2577,8 +2573,7 @@ bool Configure::verifyConfiguration()
}
if (dictionary["DYNAMICGL"] == "yes") {
- // Note that d3d11 is still allowed for ANGLE, hence the check for == "yes".
- if (dictionary["OPENGL_ES_2"] == "yes" || dictionary["ANGLE"] == "yes") {
+ if (dictionary["OPENGL_ES_2"] == "yes" || dictionary["ANGLE"] != "no") {
cout << "ERROR: Dynamic OpenGL cannot be used with -angle." << endl;
dictionary[ "DONE" ] = "error";
}
@@ -2660,15 +2655,11 @@ void Configure::generateOutputVars()
// ANGLE --------------------------------------------------------
if (dictionary[ "ANGLE" ] != "no") {
qtConfig += "angle";
- if (dictionary[ "ANGLE" ] == "d3d11")
- qmakeConfig += "angle_d3d11";
}
// Dynamic OpenGL loading ---------------------------------------
if (dictionary[ "DYNAMICGL" ] != "no") {
qtConfig += "dynamicgl";
- if (dictionary[ "ANGLE" ] == "d3d11")
- qmakeConfig += "angle_d3d11";
}
// Image formates -----------------------------------------------