From fe849f50ca83f50f6068b7d494cb228fae1d6309 Mon Sep 17 00:00:00 2001
From: Gunnar Sletta <gunnar@trolltech.com>
Date: Mon, 1 Feb 2010 14:30:01 +0100
Subject: Geometry Shader support in QGLShaderProgram

---
 src/opengl/qglextensions.cpp    |   6 ++
 src/opengl/qglextensions_p.h    |  46 ++++++++++++
 src/opengl/qglshaderprogram.cpp | 153 ++++++++++++++++++++++++++++++++++++++++
 src/opengl/qglshaderprogram.h   |  24 ++++++-
 4 files changed, 228 insertions(+), 1 deletion(-)

diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp
index c091191..a4b2dc1 100644
--- a/src/opengl/qglextensions.cpp
+++ b/src/opengl/qglextensions.cpp
@@ -220,6 +220,12 @@ bool qt_resolve_buffer_extensions(QGLContext *ctx)
 
 bool qt_resolve_glsl_extensions(QGLContext *ctx)
 {
+    // Geometry shaders are optional...
+    glProgramParameteriEXT = (_glProgramParameteriEXT) ctx->getProcAddress(QLatin1String("glProgramParameteriEXT"));
+    glFramebufferTextureEXT = (_glFramebufferTextureEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureEXT"));
+    glFramebufferTextureLayerEXT = (_glFramebufferTextureLayerEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureLayerEXT"));
+    glFramebufferTextureFaceEXT = (_glFramebufferTextureFaceEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureFaceEXT"));
+
 #if defined(QT_OPENGL_ES_2)
     // The GLSL shader functions are always present in OpenGL/ES 2.0.
     // The only exceptions are glGetProgramBinaryOES and glProgramBinaryOES.
diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h
index 86096d2..e65e3a1 100644
--- a/src/opengl/qglextensions_p.h
+++ b/src/opengl/qglextensions_p.h
@@ -184,6 +184,15 @@ typedef void (APIENTRY *_glBlitFramebufferEXT) (int srcX0, int srcY0, int srcX1,
 typedef void (APIENTRY *_glRenderbufferStorageMultisampleEXT) (GLenum target, GLsizei samples,
                                                                GLenum internalformat, GLsizei width, GLsizei height);
 
+// GL_EXT_geometry_shader4
+typedef void (APIENTRY *_glProgramParameteriEXT)(GLuint program, GLenum pname, GLint value);
+typedef void (APIENTRY *_glFramebufferTextureEXT)(GLenum target, GLenum attachment,
+                                                  GLuint texture, GLint level);
+typedef void (APIENTRY *_glFramebufferTextureLayerEXT)(GLenum target, GLenum attachment,
+                                                       GLuint texture, GLint level, GLint layer);
+typedef void (APIENTRY *_glFramebufferTextureFaceEXT)(GLenum target, GLenum attachment,
+                                                      GLuint texture, GLint level, GLenum face);
+
 // ARB_texture_compression
 typedef void (APIENTRY *_glCompressedTexImage2DARB) (GLenum, GLint, GLenum, GLsizei,
                                                      GLsizei, GLint, GLsizei, const GLvoid *);
@@ -294,6 +303,10 @@ struct QGLExtensionFuncs
         qt_glMapBufferARB = 0;
         qt_glUnmapBufferARB = 0;
 
+        qt_glProgramParameteriEXT = 0;
+        qt_glFramebufferTextureEXT = 0;
+        qt_glFramebufferTextureLayerEXT = 0;
+        qt_glFramebufferTextureFaceEXT = 0;
 #if !defined(QT_OPENGL_ES)
         // Texture compression
         qt_glCompressedTexImage2DARB = 0;
@@ -406,6 +419,11 @@ struct QGLExtensionFuncs
     _glMapBufferARB qt_glMapBufferARB;
     _glUnmapBufferARB qt_glUnmapBufferARB;
 
+    // Geometry shaders...
+    _glProgramParameteriEXT qt_glProgramParameteriEXT;
+    _glFramebufferTextureEXT qt_glFramebufferTextureEXT;
+    _glFramebufferTextureLayerEXT qt_glFramebufferTextureLayerEXT;
+    _glFramebufferTextureFaceEXT qt_glFramebufferTextureFaceEXT;
 #if !defined(QT_OPENGL_ES)
     // Texture compression
     _glCompressedTexImage2DARB qt_glCompressedTexImage2DARB;
@@ -642,6 +660,29 @@ struct QGLExtensionFuncs
 #define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
 #endif
 
+// Geometry shader defines
+#ifndef GL_GEOMETRY_SHADER_EXT
+#  define GL_GEOMETRY_SHADER_EXT 0x8DD9
+#  define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA
+#  define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB
+#  define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC
+#  define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29
+#  define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD
+#  define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE
+#  define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B
+#  define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF
+#  define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0
+#  define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1
+#  define GL_LINES_ADJACENCY_EXT 0xA
+#  define GL_LINE_STRIP_ADJACENCY_EXT 0xB
+#  define GL_TRIANGLES_ADJACENCY_EXT 0xC
+#  define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD
+#  define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8
+#  define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9
+#  define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7
+#  define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4
+#  define GL_PROGRAM_POINT_SIZE_EXT 0x8642
+#endif
 
 #if !defined(QT_OPENGL_ES_2)
 #define glProgramStringARB QGLContextPrivate::extensionFuncs(ctx).qt_glProgramStringARB
@@ -759,6 +800,11 @@ struct QGLExtensionFuncs
 #define glClearDepth glClearDepthf
 #endif
 
+#define glProgramParameteriEXT QGLContextPrivate::extensionFuncs(ctx).qt_glProgramParameteriEXT
+#define glFramebufferTextureEXT QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTextureEXT
+#define glFramebufferTextureLayerEXT QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTextureLayerEXT
+#define glFramebufferTextureFaceEXT QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTextureFaceEXT
+
 #if !defined(QT_OPENGL_ES)
 #define glCompressedTexImage2D QGLContextPrivate::extensionFuncs(ctx).qt_glCompressedTexImage2DARB
 #endif
diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp
index 5e2f1f5..43d1df8 100644
--- a/src/opengl/qglshaderprogram.cpp
+++ b/src/opengl/qglshaderprogram.cpp
@@ -213,6 +213,8 @@ bool QGLShaderPrivate::create()
         GLuint shader;
         if (shaderType == QGLShader::Vertex)
             shader = glCreateShader(GL_VERTEX_SHADER);
+        else if (shaderType == QGLShader::Geometry)
+            shader = glCreateShader(GL_GEOMETRY_SHADER_EXT);
         else
             shader = glCreateShader(GL_FRAGMENT_SHADER);
         if (!shader) {
@@ -496,6 +498,10 @@ GLuint QGLShader::shaderId() const
     return d->shaderGuard.id();
 }
 
+
+
+
+
 #undef ctx
 #define ctx programGuard.context()
 
@@ -508,8 +514,12 @@ public:
         , linked(false)
         , inited(false)
         , removingShaders(false)
+        , geometryVertexCount(64)
+        , geometryInputType(0)
+        , geometryOutputType(0)
         , vertexShader(0)
         , fragmentShader(0)
+        , geometryShader(0)
     {
     }
     ~QGLShaderProgramPrivate();
@@ -518,11 +528,17 @@ public:
     bool linked;
     bool inited;
     bool removingShaders;
+
+    int geometryVertexCount;
+    GLenum geometryInputType;
+    GLenum geometryOutputType;
+
     QString log;
     QList<QGLShader *> shaders;
     QList<QGLShader *> anonShaders;
     QGLShader *vertexShader;
     QGLShader *fragmentShader;
+    QGLShader *geometryShader;
 
     bool hasShader(QGLShader::ShaderType type) const;
 };
@@ -820,6 +836,22 @@ bool QGLShaderProgram::link()
     GLuint program = d->programGuard.id();
     if (!program)
         return false;
+
+    // Set up the geometry shader parameters
+    if (glProgramParameteriEXT) {
+        foreach (QGLShader *shader, d->shaders) {
+            if (shader->shaderType() & QGLShader::Geometry) {
+                glProgramParameteriEXT(program, GL_GEOMETRY_INPUT_TYPE_EXT,
+                                       d->geometryInputType);
+                glProgramParameteriEXT(program, GL_GEOMETRY_OUTPUT_TYPE_EXT,
+                                       d->geometryOutputType);
+                glProgramParameteriEXT(program, GL_GEOMETRY_VERTICES_OUT_EXT,
+                                       d->geometryVertexCount);
+                break;
+            }
+        }
+    }
+
     glLinkProgram(program);
     GLint value = 0;
     glGetProgramiv(program, GL_LINK_STATUS, &value);
@@ -2830,6 +2862,97 @@ void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x4 *
 #undef ctx
 
 /*!
+    Returns the hardware limit for how many vertices a geometry shader
+    can output.
+
+    \sa setGeometryShaderOutputVertexCount
+*/
+int QGLShaderProgram::maxGeometryOutputVertices() const
+{
+    int n;
+    glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, &n);
+    return n;
+}
+
+
+
+/*!
+    Sets the maximum number of vertices the current geometry shader
+    program will produce, if active.
+
+    This parameter takes effect the next time the program is linked.
+*/
+void QGLShaderProgram::setGeometryOutputVertexCount(int count)
+{
+#ifndef QT_NO_DEBUG
+    int max = maxGeometryOutputVertices();
+    if (count > max) {
+        qWarning("QGLShaderProgram::setGeometryOutputVertexCount: count: %d higher than maximum: %d",
+                 count, max);
+    }
+#endif
+    d_func()->geometryVertexCount = count;
+}
+
+
+/*!
+    Returns the maximum number of vertices the current geometry shader
+    program will produce, if active.
+
+    This parameter takes effect the ntext time the program is linked.
+*/
+int QGLShaderProgram::geometryOutputVertexCount() const
+{
+    return d_func()->geometryVertexCount;
+}
+
+
+/*!
+    Sets the output type from the geometry shader, if active.
+
+    This parameter takes effect the next time the program is linked.
+*/
+void QGLShaderProgram::setGeometryInputType(GLenum inputType)
+{
+    d_func()->geometryInputType = inputType;
+}
+
+
+/*!
+    Returns the geometry shader input type, if active.
+
+    This parameter takes effect the next time the program is linked.
+ */
+
+GLenum QGLShaderProgram::geometryInputType() const
+{
+    return d_func()->geometryInputType;
+}
+
+
+/*!
+    Sets the output type from the geometry shader, if active.
+
+    This parameter takes effect the next time the program is linked.
+*/
+void QGLShaderProgram::setGeometryOutputType(GLenum outputType)
+{
+    d_func()->geometryOutputType = outputType;
+}
+
+
+/*!
+    Returns the geometry shader output type, if active.
+
+    This parameter takes effect the next time the program is linked.
+ */
+GLenum QGLShaderProgram::geometryOutputType() const
+{
+    return d_func()->geometryOutputType;
+}
+
+
+/*!
     Returns true if shader programs written in the OpenGL Shading
     Language (GLSL) are supported on this system; false otherwise.
 
@@ -2861,6 +2984,36 @@ void QGLShaderProgram::shaderDestroyed()
         removeShader(shader);
 }
 
+
+#undef ctx
+#undef context
+
+/*!
+    Returns true if shader programs of type \a type are supported on
+    this system; false otherwise.
+
+    The \a context is used to resolve the GLSL extensions.
+    If \a context is null, then QGLContext::currentContext() is used.
+*/
+bool QGLShader::hasShaders(ShaderType type, const QGLContext *context)
+{
+#if !defined(QT_OPENGL_ES_2)
+    if (!context)
+        context = QGLContext::currentContext();
+    if (!context)
+        return false;
+#endif
+    bool resolved = qt_resolve_glsl_extensions(const_cast<QGLContext *>(context));
+    if (!resolved)
+        return false;
+    const QGLContext *ctx = context;
+    if ((type & Geometry) && !glProgramParameteriEXT)
+        return false;
+    return true;
+}
+
+
+
 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
 /*! \internal */
 void QGLShaderProgram::setUniformValue(int location, QMacCompatGLint value)
diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h
index 24ab986..face66e 100644
--- a/src/opengl/qglshaderprogram.h
+++ b/src/opengl/qglshaderprogram.h
@@ -66,7 +66,8 @@ public:
     enum ShaderTypeBit
     {
         Vertex          = 0x0001,
-        Fragment        = 0x0002
+        Fragment        = 0x0002,
+        Geometry        = 0x0004
     };
     Q_DECLARE_FLAGS(ShaderType, ShaderTypeBit)
 
@@ -88,6 +89,8 @@ public:
 
     GLuint shaderId() const;
 
+    static bool hasShaders(ShaderType type, const QGLContext *context = 0);
+
 private:
     friend class QGLShaderProgram;
 
@@ -104,6 +107,14 @@ class Q_OPENGL_EXPORT QGLShaderProgram : public QObject
 {
     Q_OBJECT
 public:
+    enum GeometryTypes
+    {
+        LinesWithAdjacencyGeometryType          = 0xa,
+        LineStripWithAdjacencyGeometryType      = 0xb,
+        TrianglesWithAdjacencyGeometryType      = 0xc,
+        TriangleStripWithAdjacencyGeometryType  = 0xd
+    };
+
     explicit QGLShaderProgram(QObject *parent = 0);
     explicit QGLShaderProgram(const QGLContext *context, QObject *parent = 0);
     virtual ~QGLShaderProgram();
@@ -128,6 +139,17 @@ public:
 
     GLuint programId() const;
 
+    int maxGeometryOutputVertices() const;
+
+    void setGeometryOutputVertexCount(int count);
+    int geometryOutputVertexCount() const;
+
+    void setGeometryInputType(GLenum inputType);
+    GLenum geometryInputType() const;
+
+    void setGeometryOutputType(GLenum outputType);
+    GLenum geometryOutputType() const;
+
     void bindAttributeLocation(const char *name, int location);
     void bindAttributeLocation(const QByteArray& name, int location);
     void bindAttributeLocation(const QString& name, int location);
-- 
cgit v0.12


From 760319b312aceb2cc7438ad09eecd305c1b663e8 Mon Sep 17 00:00:00 2001
From: Gunnar Sletta <gunnar@trolltech.com>
Date: Thu, 4 Feb 2010 06:48:30 -0800
Subject: Fix Geometry shaders based on review

---
 src/opengl/qglshaderprogram.cpp | 24 +++++++++++++++---------
 src/opengl/qglshaderprogram.h   |  2 +-
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp
index 43d1df8..7af488d 100644
--- a/src/opengl/qglshaderprogram.cpp
+++ b/src/opengl/qglshaderprogram.cpp
@@ -517,9 +517,6 @@ public:
         , geometryVertexCount(64)
         , geometryInputType(0)
         , geometryOutputType(0)
-        , vertexShader(0)
-        , fragmentShader(0)
-        , geometryShader(0)
     {
     }
     ~QGLShaderProgramPrivate();
@@ -536,9 +533,6 @@ public:
     QString log;
     QList<QGLShader *> shaders;
     QList<QGLShader *> anonShaders;
-    QGLShader *vertexShader;
-    QGLShader *fragmentShader;
-    QGLShader *geometryShader;
 
     bool hasShader(QGLShader::ShaderType type) const;
 };
@@ -564,6 +558,17 @@ bool QGLShaderProgramPrivate::hasShader(QGLShader::ShaderType type) const
 #define ctx d->programGuard.context()
 
 /*!
+    \enum GeometryTypes
+
+    Defines the geometry types specificed by the GL_EXT_geometry_shader4 extension
+
+    \value LinesWithAdjacencyGeometryType Corresponds to GL_LINES_ADJACENCY.
+    \value LineStripWithAdjacencyGeometryType Corresponds to GL_LINE_STRIP_ADJACENCY.
+    \value TrianglesWithAdjacencyGeometryType Corresponds to GL_TRIANGLES_ADJACENCY.
+    \value TriangleStripWithAdjacencyGeometryType Corresponds to GL_TRIANGLE_STRIP_ADJACENCY.
+ */
+
+/*!
     Constructs a new shader program and attaches it to \a parent.
     The program will be invalid until addShader() is called.
 
@@ -2995,7 +3000,7 @@ void QGLShaderProgram::shaderDestroyed()
     The \a context is used to resolve the GLSL extensions.
     If \a context is null, then QGLContext::currentContext() is used.
 */
-bool QGLShader::hasShaders(ShaderType type, const QGLContext *context)
+bool QGLShader::hasOpenGLShaders(ShaderType type, const QGLContext *context)
 {
 #if !defined(QT_OPENGL_ES_2)
     if (!context)
@@ -3006,9 +3011,10 @@ bool QGLShader::hasShaders(ShaderType type, const QGLContext *context)
     bool resolved = qt_resolve_glsl_extensions(const_cast<QGLContext *>(context));
     if (!resolved)
         return false;
-    const QGLContext *ctx = context;
-    if ((type & Geometry) && !glProgramParameteriEXT)
+
+    if ((type & Geometry) && !QByteArray((const char *) glGetString(GL_EXTENSIONS)).contains("GL_EXT_geometry_shader4"))
         return false;
+
     return true;
 }
 
diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h
index face66e..6dfbb77 100644
--- a/src/opengl/qglshaderprogram.h
+++ b/src/opengl/qglshaderprogram.h
@@ -89,7 +89,7 @@ public:
 
     GLuint shaderId() const;
 
-    static bool hasShaders(ShaderType type, const QGLContext *context = 0);
+    static bool hasOpenGLShaders(ShaderType type, const QGLContext *context = 0);
 
 private:
     friend class QGLShaderProgram;
-- 
cgit v0.12


From e98c07e5247a5ad4876c4add595ec1897b73b190 Mon Sep 17 00:00:00 2001
From: Gunnar Sletta <gunnar@trolltech.com>
Date: Mon, 8 Feb 2010 13:03:34 +0100
Subject: Another round of Geometry shader review.

Reviewed-by: Trond
---
 src/opengl/qglshaderprogram.cpp | 18 +++++-------------
 src/opengl/qglshaderprogram.h   | 16 ++++++++--------
 2 files changed, 13 insertions(+), 21 deletions(-)

diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp
index 7af488d..22db731 100644
--- a/src/opengl/qglshaderprogram.cpp
+++ b/src/opengl/qglshaderprogram.cpp
@@ -558,17 +558,6 @@ bool QGLShaderProgramPrivate::hasShader(QGLShader::ShaderType type) const
 #define ctx d->programGuard.context()
 
 /*!
-    \enum GeometryTypes
-
-    Defines the geometry types specificed by the GL_EXT_geometry_shader4 extension
-
-    \value LinesWithAdjacencyGeometryType Corresponds to GL_LINES_ADJACENCY.
-    \value LineStripWithAdjacencyGeometryType Corresponds to GL_LINE_STRIP_ADJACENCY.
-    \value TrianglesWithAdjacencyGeometryType Corresponds to GL_TRIANGLES_ADJACENCY.
-    \value TriangleStripWithAdjacencyGeometryType Corresponds to GL_TRIANGLE_STRIP_ADJACENCY.
- */
-
-/*!
     Constructs a new shader program and attaches it to \a parent.
     The program will be invalid until addShader() is called.
 
@@ -612,6 +601,7 @@ bool QGLShaderProgram::init()
         context = QGLContext::currentContext();
         d->programGuard.setContext(context);
     }
+
     if (!context)
         return false;
     if (qt_resolve_glsl_extensions(const_cast<QGLContext *>(context))) {
@@ -3002,12 +2992,14 @@ void QGLShaderProgram::shaderDestroyed()
 */
 bool QGLShader::hasOpenGLShaders(ShaderType type, const QGLContext *context)
 {
-#if !defined(QT_OPENGL_ES_2)
     if (!context)
         context = QGLContext::currentContext();
     if (!context)
         return false;
-#endif
+
+    if ((type & ~(Geometry | Vertex | Fragment)) || type == 0)
+        return false;
+
     bool resolved = qt_resolve_glsl_extensions(const_cast<QGLContext *>(context));
     if (!resolved)
         return false;
diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h
index 6dfbb77..56034ee 100644
--- a/src/opengl/qglshaderprogram.h
+++ b/src/opengl/qglshaderprogram.h
@@ -103,18 +103,18 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QGLShader::ShaderType)
 
 class QGLShaderProgramPrivate;
 
+#ifndef GL_EXT_geometry_shader4
+#  define GL_LINES_ADJACENCY_EXT 0xA
+#  define GL_LINE_STRIP_ADJACENCY_EXT 0xB
+#  define GL_TRIANGLES_ADJACENCY_EXT 0xC
+#  define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD
+#endif
+
+
 class Q_OPENGL_EXPORT QGLShaderProgram : public QObject
 {
     Q_OBJECT
 public:
-    enum GeometryTypes
-    {
-        LinesWithAdjacencyGeometryType          = 0xa,
-        LineStripWithAdjacencyGeometryType      = 0xb,
-        TrianglesWithAdjacencyGeometryType      = 0xc,
-        TriangleStripWithAdjacencyGeometryType  = 0xd
-    };
-
     explicit QGLShaderProgram(QObject *parent = 0);
     explicit QGLShaderProgram(const QGLContext *context, QObject *parent = 0);
     virtual ~QGLShaderProgram();
-- 
cgit v0.12


From 692e9103ebb85b90e79377206d5d03b704d43d42 Mon Sep 17 00:00:00 2001
From: Olivier Goffart <ogoffart@trolltech.com>
Date: Mon, 8 Feb 2010 15:27:12 +0100
Subject: QMainWindow: update the separator size when the style change

Task-number: QTBUG-2774
Reviewed-ny: Thierry
---
 src/gui/widgets/qdockarealayout.cpp        | 62 +++++++++++++++++-------------
 src/gui/widgets/qdockarealayout_p.h        |  5 ++-
 src/gui/widgets/qmainwindow.cpp            |  1 +
 tests/auto/qmainwindow/tst_qmainwindow.cpp | 40 +++++++++++++++++++
 4 files changed, 79 insertions(+), 29 deletions(-)

diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp
index d754800..13f31df 100644
--- a/src/gui/widgets/qdockarealayout.cpp
+++ b/src/gui/widgets/qdockarealayout.cpp
@@ -220,15 +220,17 @@ static quintptr tabId(const QDockAreaLayoutItem &item)
 }
 #endif
 
+static const int zero = 0;
+
 QDockAreaLayoutInfo::QDockAreaLayoutInfo()
-    : sep(0), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(0)
+    : sep(&zero), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(0)
 #ifndef QT_NO_TABBAR
     , tabbed(false), tabBar(0), tabBarShape(QTabBar::RoundedSouth), tabBarVisible(false)
 #endif
 {
 }
 
-QDockAreaLayoutInfo::QDockAreaLayoutInfo(int _sep, QInternal::DockPosition _dockPos,
+QDockAreaLayoutInfo::QDockAreaLayoutInfo(const int *_sep, QInternal::DockPosition _dockPos,
                                             Qt::Orientation _o, int tbshape,
                                             QMainWindow *window)
     : sep(_sep), dockPos(_dockPos), o(_o), mainWindow(window)
@@ -281,7 +283,7 @@ QSize QDockAreaLayoutInfo::minimumSize() const
 #endif
         {
             if (!first)
-                a += sep;
+                a += *sep;
             a += pick(o, min_size);
         }
         b = qMax(b, perp(o, min_size));
@@ -349,7 +351,7 @@ QSize QDockAreaLayoutInfo::maximumSize() const
 #endif
         {
             if (!first)
-                a += sep;
+                a += *sep;
             a += pick(o, max_size);
         }
         b = qMin(b, perp(o, max_size));
@@ -415,7 +417,7 @@ QSize QDockAreaLayoutInfo::sizeHint() const
         {
             if (previous && !gap && !(previous->flags &  QDockAreaLayoutItem::GapItem)
                 && !previous->hasFixedSize(o)) {
-                a += sep;
+                a += *sep;
             }
             a += gap ? item.size : pick(o, size_hint);
         }
@@ -491,7 +493,7 @@ static int realMinSize(const QDockAreaLayoutInfo &info)
             min = pick(info.o, item.minimumSize());
 
         if (!first)
-            result += info.sep;
+            result += *info.sep;
         result += min;
 
         first = false;
@@ -516,7 +518,7 @@ static int realMaxSize(const QDockAreaLayoutInfo &info)
             max = pick(info.o, item.maximumSize());
 
         if (!first)
-            result += info.sep;
+            result += *info.sep;
         result += max;
 
         if (result >= QWIDGETSIZE_MAX)
@@ -555,7 +557,7 @@ void QDockAreaLayoutInfo::fitItems()
             if (!(previous->flags & QDockAreaLayoutItem::GapItem)) {
                 QLayoutStruct &ls = layout_struct_list[j++];
                 ls.init();
-                ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : sep;
+                ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : *sep;
                 ls.empty = false;
             }
         }
@@ -938,7 +940,7 @@ int QDockAreaLayoutInfo::separatorMove(int index, int delta)
         if (item.skip()) {
             ls.empty = true;
         } else {
-            const int separatorSpace = item.hasFixedSize(o) ? 0 : sep;
+            const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep;
             ls.empty = false;
             ls.pos = item.pos;
             ls.size = item.size + separatorSpace;
@@ -956,7 +958,7 @@ int QDockAreaLayoutInfo::separatorMove(int index, int delta)
         if (item.skip())
             continue;
         QLayoutStruct &ls = list[i];
-        const int separatorSpace = item.hasFixedSize(o) ? 0 : sep;
+        const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep;
         item.size = ls.size - separatorSpace;
         item.pos = ls.pos;
         if (item.subinfo != 0) {
@@ -1041,11 +1043,11 @@ QLayoutItem *QDockAreaLayoutInfo::plug(const QList<int> &path)
         int next = this->next(index);
 
         if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
-            item.pos += sep;
-            item.size -= sep;
+            item.pos += *sep;
+            item.size -= *sep;
         }
         if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
-            item.size -= sep;
+            item.size -= *sep;
 
         QPoint pos;
         rpick(o, pos) = item.pos;
@@ -1083,11 +1085,11 @@ QLayoutItem *QDockAreaLayoutInfo::unplug(const QList<int> &path)
 #endif
     {
         if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
-            item.pos -= sep;
-            item.size += sep;
+            item.pos -= *sep;
+            item.size += *sep;
         }
         if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
-            item.size += sep;
+            item.size += *sep;
     }
 
     return item.widgetItem;
@@ -1255,9 +1257,9 @@ bool QDockAreaLayoutInfo::insertGap(const QList<int> &path, QLayoutItem *dockWid
             QRect r = dockedGeometry(dockWidgetItem->widget());
             gap_size = pick(o, r.size());
         if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem))
-                sep_size += sep;
+                sep_size += *sep;
             if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
-                sep_size += sep;
+                sep_size += *sep;
         }
         if (gap_size + sep_size > space)
             gap_size = pick(o, gap_item.minimumSize());
@@ -1364,7 +1366,7 @@ QRect QDockAreaLayoutInfo::separatorRect(int index) const
     QPoint pos = rect.topLeft();
     rpick(o, pos) = item.pos + item.size;
     QSize s = rect.size();
-    rpick(o, s) = sep;
+    rpick(o, s) = *sep;
 
     return QRect(pos, s);
 }
@@ -1413,7 +1415,7 @@ QList<int> QDockAreaLayoutInfo::findSeparator(const QPoint &_pos) const
             continue;
 
         QRect sepRect = separatorRect(i);
-        if (!sepRect.isNull() && sep == 1)
+        if (!sepRect.isNull() && *sep == 1)
             sepRect.adjust(-2, -2, 2, 2);
         //we also make sure we don't find a separator that's not there
         if (sepRect.contains(_pos) && !item.hasFixedSize(o)) {
@@ -1560,7 +1562,7 @@ void QDockAreaLayoutInfo::apply(bool animate)
         }
     }
 #ifndef QT_NO_TABBAR
-    if (sep == 1)
+    if (*sep == 1)
         updateSeparatorWidgets();
 #endif //QT_NO_TABBAR
 }
@@ -2010,7 +2012,7 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*>
         updateTabBar();
         setCurrentTabId(tabId(item_list.at(index)));
     }
-    if (!testing && sep == 1)
+    if (!testing && *sep == 1)
         updateSeparatorWidgets();
 #endif
 
@@ -2273,13 +2275,13 @@ QDockAreaLayout::QDockAreaLayout(QMainWindow *win) : fallbackToSizeHints(true)
     const int tabShape = 0;
 #endif
     docks[QInternal::LeftDock]
-        = QDockAreaLayoutInfo(sep, QInternal::LeftDock, Qt::Vertical, tabShape, win);
+        = QDockAreaLayoutInfo(&sep, QInternal::LeftDock, Qt::Vertical, tabShape, win);
     docks[QInternal::RightDock]
-        = QDockAreaLayoutInfo(sep, QInternal::RightDock, Qt::Vertical, tabShape, win);
+        = QDockAreaLayoutInfo(&sep, QInternal::RightDock, Qt::Vertical, tabShape, win);
     docks[QInternal::TopDock]
-        = QDockAreaLayoutInfo(sep, QInternal::TopDock, Qt::Horizontal, tabShape, win);
+        = QDockAreaLayoutInfo(&sep, QInternal::TopDock, Qt::Horizontal, tabShape, win);
     docks[QInternal::BottomDock]
-        = QDockAreaLayoutInfo(sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win);
+        = QDockAreaLayoutInfo(&sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win);
     centralWidgetItem = 0;
 
 
@@ -3028,7 +3030,7 @@ void QDockAreaLayout::addDockWidget(QInternal::DockPosition pos, QDockWidget *do
 #else
         int tbshape = 0;
 #endif
-        QDockAreaLayoutInfo new_info(sep, pos, orientation, tbshape, mainWindow);
+        QDockAreaLayoutInfo new_info(&sep, pos, orientation, tbshape, mainWindow);
         new_info.item_list.append(new QDockAreaLayoutInfo(info));
         new_info.item_list.append(dockWidgetItem);
         info = new_info;
@@ -3324,6 +3326,12 @@ void QDockAreaLayout::keepSize(QDockWidget *w)
         item.flags |= QDockAreaLayoutItem::KeepSize;
 }
 
+void QDockAreaLayout::styleChangedEvent()
+{
+    sep = mainWindow->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, mainWindow);
+    fitLayout();
+}
+
 QT_END_NAMESPACE
 
 #endif // QT_NO_DOCKWIDGET
diff --git a/src/gui/widgets/qdockarealayout_p.h b/src/gui/widgets/qdockarealayout_p.h
index 0bc1aa9..0088f00 100644
--- a/src/gui/widgets/qdockarealayout_p.h
+++ b/src/gui/widgets/qdockarealayout_p.h
@@ -128,7 +128,7 @@ class Q_AUTOTEST_EXPORT QDockAreaLayoutInfo
 {
 public:
     QDockAreaLayoutInfo();
-    QDockAreaLayoutInfo(int _sep, QInternal::DockPosition _dockPos, Qt::Orientation _o,
+    QDockAreaLayoutInfo(const int *_sep, QInternal::DockPosition _dockPos, Qt::Orientation _o,
                         int tbhape, QMainWindow *window);
 
     QSize minimumSize() const;
@@ -189,7 +189,7 @@ public:
 
     QMainWindowLayout *mainWindowLayout() const;
 
-    int sep;
+    const int *sep;
     mutable QVector<QWidget*> separatorWidgets;
     QInternal::DockPosition dockPos;
     Qt::Orientation o;
@@ -300,6 +300,7 @@ public:
     QSet<QTabBar*> usedTabBars() const;
     QSet<QWidget*> usedSeparatorWidgets() const;
 #endif //QT_NO_TABBAR
+    void styleChangedEvent();
 };
 
 QT_END_NAMESPACE
diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp
index 269cd12..eb25417 100644
--- a/src/gui/widgets/qmainwindow.cpp
+++ b/src/gui/widgets/qmainwindow.cpp
@@ -1393,6 +1393,7 @@ bool QMainWindow::event(QEvent *event)
 #endif // QT_NO_STATUSTIP
 
         case QEvent::StyleChange:
+            d->layout->layoutState.dockAreaLayout.styleChangedEvent();
             if (!d->explicitIconSize)
                 setIconSize(QSize());
             break;
diff --git a/tests/auto/qmainwindow/tst_qmainwindow.cpp b/tests/auto/qmainwindow/tst_qmainwindow.cpp
index b1c44be..1273e85 100644
--- a/tests/auto/qmainwindow/tst_qmainwindow.cpp
+++ b/tests/auto/qmainwindow/tst_qmainwindow.cpp
@@ -108,6 +108,7 @@ private slots:
     void addToolbarAfterShow();
     void centralWidgetSize();
     void dockWidgetSize();
+    void QTBUG2774_stylechange();
 };
 
 // Testing get/set functions
@@ -1709,6 +1710,45 @@ void tst_QMainWindow::dockWidgetSize()
     }
 }
 
+void tst_QMainWindow::QTBUG2774_stylechange()
+{
+
+    QMainWindow mw;
+    QDockWidget *dockw = new QDockWidget();
+    mw.addDockWidget(Qt::LeftDockWidgetArea, dockw);
+    mw.addDockWidget(Qt::LeftDockWidgetArea, new QDockWidget());
+    QTextEdit *central = new QTextEdit(&mw);
+    mw.setCentralWidget(central);
+    dockw->resize(10,10);
+    mw.show();
+    QTest::qWaitForWindowShown(&mw);
+    int centralOriginalWidth = central->width();
+
+    QVERIFY(!mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height() - 3)));
+    QVERIFY( mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height())));
+    QVERIFY(!mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height() + 30)));
+
+
+    {
+        QTest::qWait(1000);
+        mw.setStyleSheet("QMainWindow::separator {  width: 50px; height:50px; }");
+        QTest::qWait(5000);
+        QApplication::processEvents();
+        QVERIFY(central->width() < centralOriginalWidth);
+        QVERIFY( mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height())));
+        QVERIFY( mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height() + 49)));
+    }
+
+    {
+        mw.setStyleSheet("QMainWindow::separator {  width: 0px; height: 0px; }");
+        QApplication::processEvents();
+        QVERIFY(central->width() > centralOriginalWidth);
+        QVERIFY(!mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height())));
+        QVERIFY(!mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height() + 1)));
+    }
+}
+
+
 
 QTEST_MAIN(tst_QMainWindow)
 #include "tst_qmainwindow.moc"
-- 
cgit v0.12


From 8a81562af30435f82255830489dca691031a5408 Mon Sep 17 00:00:00 2001
From: aavit <qt-info@nokia.com>
Date: Tue, 9 Feb 2010 10:32:04 +0100
Subject: Use libpng API as recommended. Preparation for upgrade to libpng
 1.4.0.

The libpng doc advises against accessing the info_ptr structure
directly, and in 1.4.0 the members are flagged as deprecated, so such
access gives compilation warnings. This patch makes qpnghandler use
the recommended access functions instead.

Reviewed-by: Trond
---
 src/gui/image/qpnghandler.cpp | 135 +++++++++++++++++++-----------------------
 1 file changed, 62 insertions(+), 73 deletions(-)

diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index d5406cb..bba54b9 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -50,8 +50,13 @@
 #include <qvariant.h>
 #include <qvector.h>
 
+#ifdef QT_USE_BUNDLED_LIBPNG
+#include <../../3rdparty/libpng/png.h>
+#include <../../3rdparty/libpng/pngconf.h>
+#else
 #include <png.h>
 #include <pngconf.h>
+#endif
 
 #ifdef Q_OS_WINCE
 #define CALLBACK_CALL_TYPE        __cdecl
@@ -162,11 +167,16 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre
     png_uint_32 height;
     int bit_depth;
     int color_type;
+    png_bytep trans_alpha = 0;
+    png_color_16p trans_color_p = 0;
+    int num_trans;
+    png_colorp palette = 0;
+    int num_palette;
     png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
 
     if (color_type == PNG_COLOR_TYPE_GRAY) {
         // Black & White or 8-bit grayscale
-        if (bit_depth == 1 && info_ptr->channels == 1) {
+        if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
             png_set_invert_mono(png_ptr);
             png_read_update_info(png_ptr, info_ptr);
             if (image.size() != QSize(width, height) || image.format() != QImage::Format_Mono) {
@@ -207,20 +217,16 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre
                 int c = i*255/(ncols-1);
                 image.setColor(i, qRgba(c,c,c,0xff));
             }
-            if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
-#if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4)
-                const int g = info_ptr->trans_values.gray;
-#else
-                const int g = info_ptr->trans_color.gray;
-#endif
+            if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_color_p) {
+                const int g = trans_color_p->gray;
                 if (g < ncols) {
                     image.setColor(g, 0);
                 }
             }
         }
     } else if (color_type == PNG_COLOR_TYPE_PALETTE
-               && png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)
-               && info_ptr->num_palette <= 256)
+               && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)
+               && num_palette <= 256)
     {
         // 1-bit and 8-bit color
         if (bit_depth != 1)
@@ -233,29 +239,26 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre
             if (image.isNull())
                 return;
         }
-        image.setColorCount(info_ptr->num_palette);
+        png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
+        image.setColorCount(num_palette);
         int i = 0;
-        if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
-            while (i < info_ptr->num_trans) {
+        if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_alpha) {
+            while (i < num_trans) {
                 image.setColor(i, qRgba(
-                    info_ptr->palette[i].red,
-                    info_ptr->palette[i].green,
-                    info_ptr->palette[i].blue,
-#if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4)
-                    info_ptr->trans[i]
-#else
-                    info_ptr->trans_alpha[i]
-#endif
+                    palette[i].red,
+                    palette[i].green,
+                    palette[i].blue,
+                    trans_alpha[i]
                    )
                );
                 i++;
             }
         }
-        while (i < info_ptr->num_palette) {
+        while (i < num_palette) {
             image.setColor(i, qRgba(
-                info_ptr->palette[i].red,
-                info_ptr->palette[i].green,
-                info_ptr->palette[i].blue,
+                palette[i].red,
+                palette[i].green,
+                palette[i].blue,
                 0xff
                )
            );
@@ -531,33 +534,36 @@ QImage::Format QPngHandlerPrivate::readImageFormat()
         QImage::Format format = QImage::Format_Invalid;
         png_uint_32 width, height;
         int bit_depth, color_type;
-        if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY) {
+        png_colorp palette;
+        int num_palette;
+        png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
+        if (color_type == PNG_COLOR_TYPE_GRAY) {
             // Black & White or 8-bit grayscale
-            if (info_ptr->bit_depth == 1 && info_ptr->channels == 1) {
+            if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
                 format = QImage::Format_Mono;
-            } else if (info_ptr->bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+            } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
                 format = QImage::Format_ARGB32;
             } else {
                 format = QImage::Format_Indexed8;
             }
-        } else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE
-                && png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)
-                   && info_ptr->num_palette <= 256)
+        } else if (color_type == PNG_COLOR_TYPE_PALETTE
+                   && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)
+                   && num_palette <= 256)
         {
             // 1-bit and 8-bit color
-            if (info_ptr->bit_depth != 1)
+            if (bit_depth != 1)
                 png_set_packing(png_ptr);
             png_read_update_info(png_ptr, info_ptr);
             png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
             format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8;
         } else {
             // 32-bit
-            if (info_ptr->bit_depth == 16)
+            if (bit_depth == 16)
                 png_set_strip_16(png_ptr);
 
             format = QImage::Format_ARGB32;
             // Only add filler if no alpha, or we can get 5 channel data.
-            if (!(info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
+            if (!(color_type & PNG_COLOR_MASK_ALPHA)
                 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
                 // We want 4 bytes, but it isn't an alpha channel
                 format = QImage::Format_RGB32;
@@ -648,7 +654,7 @@ static void set_text(const QImage &image, png_structp png_ptr, png_infop info_pt
         text_ptr[i].text = qstrdup(value.constData());
         text_ptr[i].text_length = 0;
         text_ptr[i].itxt_length = value.size();
-        text_ptr[i].lang = "UTF-8";
+        text_ptr[i].lang = const_cast<char*>("UTF-8");
         text_ptr[i].lang_key = qstrdup(it.key().toUtf8().constData());
 #endif
         ++i;
@@ -735,64 +741,51 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in,
         png_set_compression_level(png_ptr, quality);
     }
 
-    if (gamma != 0.0) {
-        png_set_gAMA(png_ptr, info_ptr, 1.0/gamma);
-    }
-
     png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn);
 
-    info_ptr->channels =
-        (image.depth() == 32)
-        ? (image.format() == QImage::Format_RGB32 ? 3 : 4)
-        : 1;
-
     png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(),
         image.depth() == 1 ? 1 : 8 /* per channel */,
         image.depth() == 32
             ? image.format() == QImage::Format_RGB32
                 ? PNG_COLOR_TYPE_RGB
                 : PNG_COLOR_TYPE_RGB_ALPHA
-            : PNG_COLOR_TYPE_PALETTE, 0, 0, 0);
+            : PNG_COLOR_TYPE_PALETTE, 0, 0, 0);  // also sets #channels
 
+    if (gamma != 0.0) {
+        png_set_gAMA(png_ptr, info_ptr, 1.0/gamma);
+    }
 
-    //png_set_sBIT(png_ptr, info_ptr, 8);
-    info_ptr->sig_bit.red = 8;
-    info_ptr->sig_bit.green = 8;
-    info_ptr->sig_bit.blue = 8;
+    png_color_8 sig_bit;
+    sig_bit.red = 8;
+    sig_bit.green = 8;
+    sig_bit.blue = 8;
+    sig_bit.alpha = image.hasAlphaChannel() ? 8 : 0;
+    png_set_sBIT(png_ptr, info_ptr, &sig_bit);
 
     if (image.format() == QImage::Format_MonoLSB)
        png_set_packswap(png_ptr);
 
-    png_colorp palette = 0;
-    png_bytep copy_trans = 0;
     if (image.colorCount()) {
         // Paletted
         int num_palette = image.colorCount();
-        palette = new png_color[num_palette];
-        png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
-        int* trans = new int[num_palette];
+        png_color palette[num_palette];
+        png_byte trans[num_palette];
         int num_trans = 0;
         for (int i=0; i<num_palette; i++) {
-            QRgb rgb=image.color(i);
-            info_ptr->palette[i].red = qRed(rgb);
-            info_ptr->palette[i].green = qGreen(rgb);
-            info_ptr->palette[i].blue = qBlue(rgb);
-            trans[i] = rgb >> 24;
+            QRgb rgba=image.color(i);
+            palette[i].red = qRed(rgba);
+            palette[i].green = qGreen(rgba);
+            palette[i].blue = qBlue(rgba);
+            trans[i] = qAlpha(rgba);
             if (trans[i] < 255) {
                 num_trans = i+1;
             }
         }
+        png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
+
         if (num_trans) {
-            copy_trans = new png_byte[num_trans];
-            for (int i=0; i<num_trans; i++)
-                copy_trans[i] = trans[i];
-            png_set_tRNS(png_ptr, info_ptr, copy_trans, num_trans, 0);
+            png_set_tRNS(png_ptr, info_ptr, trans, num_trans, 0);
         }
-        delete [] trans;
-    }
-
-    if (image.format() != QImage::Format_RGB32) {
-        info_ptr->sig_bit.alpha = 8;
     }
 
     // Swap ARGB to RGBA (normal PNG format) before saving on
@@ -868,11 +861,6 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in,
     png_write_end(png_ptr, info_ptr);
     frames_written++;
 
-    if (palette)
-        delete [] palette;
-    if (copy_trans)
-        delete [] copy_trans;
-
     png_destroy_write_struct(&png_ptr, &info_ptr);
 
     return true;
@@ -958,7 +946,8 @@ QVariant QPngHandler::option(ImageOption option) const
     else if (option == Description)
         return d->description;
     else if (option == Size)
-        return QSize(d->info_ptr->width, d->info_ptr->height);
+        return QSize(png_get_image_width(d->png_ptr, d->info_ptr),
+                     png_get_image_height(d->png_ptr, d->info_ptr));
     else if (option == ImageFormat)
         return d->readImageFormat();
     return 0;
-- 
cgit v0.12


From 81f50bd9691dc671f9185d6a91ca0b24a8c84402 Mon Sep 17 00:00:00 2001
From: Alan Alpert <alan.alpert@nokia.com>
Date: Tue, 9 Feb 2010 10:42:20 +0100
Subject: Fix failing QDoubleValidator tests

Results seem consistent with the class documentation, and so have
altered the expected results to match. Likely a change was made to the
class internals and the auto tests were not updated.
---
 tests/auto/qdoublevalidator/tst_qdoublevalidator.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/tests/auto/qdoublevalidator/tst_qdoublevalidator.cpp b/tests/auto/qdoublevalidator/tst_qdoublevalidator.cpp
index 37dd6d8..26890b3 100644
--- a/tests/auto/qdoublevalidator/tst_qdoublevalidator.cpp
+++ b/tests/auto/qdoublevalidator/tst_qdoublevalidator.cpp
@@ -68,7 +68,7 @@ void tst_QDoubleValidator::validateThouSep_data()
     QTest::addColumn<QString>("value");
     QTest::addColumn<QValidator::State>("result");
 
-    QTest::newRow("1,000C") << "C" << QString("1,000") << INV;
+    QTest::newRow("1,000C") << "C" << QString("1,000") << ACC;
     QTest::newRow("1.000C") << "C" << QString("1.000") << ACC;
 
     QTest::newRow("1,000de") << "de" << QString("1,000") << ACC;
@@ -160,9 +160,9 @@ void tst_QDoubleValidator::validate_data()
     QTest::newRow("data_de0")  << "de" << 0.0 << 100.0 << 1 << QString("50,0") << ACC << ACC;
     QTest::newRow("data_de1")  << "de" << 00.0 << 100.0 << 1 << QString("500,0") << ITM << ITM;
     QTest::newRow("data_de1a")  << "de" << 00.0 << 100.0 << 1 << QString("5001,0") << ITM << INV;
-    QTest::newRow("data_de0C")  << "de" << 0.0 << 100.0 << 1 << QString("50.0") << ACC << ACC;
-    QTest::newRow("data_de1C")  << "de" << 00.0 << 100.0 << 1 << QString("500.0") << ITM << ITM;
-    QTest::newRow("data_de1aC")  << "de" << 00.0 << 100.0 << 1 << QString("5001.0") << ITM << INV;
+    QTest::newRow("data_de0C")  << "de" << 0.0 << 100.0 << 1 << QString("50,0") << ACC << ACC;
+    QTest::newRow("data_de1C")  << "de" << 00.0 << 100.0 << 1 << QString("500,0") << ITM << ITM;
+    QTest::newRow("data_de1aC")  << "de" << 00.0 << 100.0 << 1 << QString("5001,0") << ITM << INV;
     QTest::newRow("data_de2")  << "de" << 00.0 << 100.0 << 1 << QString("-35,0") << INV << INV;
     QTest::newRow("data_de3")  << "de" << 00.0 << 100.0 << 1 << QString("a") << INV << INV;
     QTest::newRow("data_de4")  << "de" << 0.0 << 100.0 << 1 << QString("-") << INV << INV;
@@ -172,7 +172,7 @@ void tst_QDoubleValidator::validate_data()
     QTest::newRow("data_de8")  << "de" << -100.0 << 100.0 << 1 << QString("-100") << ACC << ACC;
     QTest::newRow("data_de9")  << "de" << -100.0 << -10.0 << 1 << QString("10") << ITM << ITM;
     QTest::newRow("data_de10") << "de" << 0.3 << 0.5 << 5 << QString("0,34567") << ACC << ACC;
-    QTest::newRow("data_de11") << "de" << -0.3 << -0.5 << 5 << QString("-0,345678") << INV << INV;
+    QTest::newRow("data_de11") << "de" << -0.3 << -0.5 << 5 << QString("-0,345678") << ITM << INV;
     QTest::newRow("data_de12") << "de" << -0.32 << 0.32 << 1 << QString("0") << ACC << ACC;
     QTest::newRow("data_de13") << "de" << 0.0 << 100.0 << 1 << QString("3456a") << INV << INV;
     QTest::newRow("data_de14") << "de" << -100.0 << 100.0 << 1 << QString("-3456a") << INV << INV;
-- 
cgit v0.12


From 6f155d010b6dd5ae3c04e62b3a29f8c0ed9f0a36 Mon Sep 17 00:00:00 2001
From: aavit <qt-info@nokia.com>
Date: Wed, 10 Feb 2010 10:05:51 +0100
Subject: Workaround for a certain functionally challenged compiler

Reviewed-by: Trond
---
 src/gui/image/qpnghandler.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index bba54b9..dd31834 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -767,9 +767,9 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in,
 
     if (image.colorCount()) {
         // Paletted
-        int num_palette = image.colorCount();
-        png_color palette[num_palette];
-        png_byte trans[num_palette];
+        int num_palette = qMin(256, image.colorCount());
+        png_color palette[256];
+        png_byte trans[256];
         int num_trans = 0;
         for (int i=0; i<num_palette; i++) {
             QRgb rgba=image.color(i);
-- 
cgit v0.12


From b7af368e86874d71ffc9071c9ef009814d6a3467 Mon Sep 17 00:00:00 2001
From: Gabriel de Dietrich <gabriel.dietrich-de@nokia.com>
Date: Tue, 9 Feb 2010 09:56:25 +0100
Subject: Crash when deleting the parent of a context menu while it is being
 displayed

Asynchronous deletion of a widget (e.g. calling deleteLater() after a timeout)
could be caught by the context menu's event loop if called with exec() instead
of popup(). This causes the context menu to be deleted twice in some cases,
and a crash generally follows.

Although this introduces a minor behaviour change, we now use popup() with the
WA_DeleteOnClose attribute to display the context menu in all the
contextMenuEvent() bodies, except in those where the menu was already
protected by a QPointer. In QDialog::contextMenuEvent(), we use QWeakPointer
to reflect the fact that the menu was previously allocated in the stack.

QAbstractSpinBox, QDialog and QMdiSubWindow keep using QMenu::exec() in
contextMenuEvent() as they need the QAction returned.

Some auto-tests included.

Reviewed-by: Olivier
Task-number: QTBUG-7902
---
 src/gui/dialogs/qdialog.cpp            |  7 ++++---
 src/gui/dialogs/qmessagebox.cpp        |  4 ++--
 src/gui/text/qtextcontrol.cpp          |  4 ++--
 src/gui/widgets/qlabel.cpp             |  4 ++--
 src/gui/widgets/qlineedit.cpp          |  6 +++---
 src/gui/widgets/qmainwindow.cpp        | 12 ++++++++----
 tests/auto/qlabel/tst_qlabel.cpp       | 24 ++++++++++++++++++++++++
 tests/auto/qlineedit/tst_qlineedit.cpp | 23 +++++++++++++++++++++++
 tests/auto/qtextedit/tst_qtextedit.cpp | 22 ++++++++++++++++++++++
 9 files changed, 90 insertions(+), 16 deletions(-)

diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp
index 9ff2ad8..fb0dba4 100644
--- a/src/gui/dialogs/qdialog.cpp
+++ b/src/gui/dialogs/qdialog.cpp
@@ -648,13 +648,14 @@ void QDialog::contextMenuEvent(QContextMenuEvent *e)
     while (w && w->whatsThis().size() == 0 && !w->testAttribute(Qt::WA_CustomWhatsThis))
         w = w->isWindow() ? 0 : w->parentWidget();
     if (w) {
-        QMenu p(this);
-        QAction *wt = p.addAction(tr("What's This?"));
-        if (p.exec(e->globalPos()) == wt) {
+        QWeakPointer<QMenu> p = new QMenu(this);
+        QAction *wt = p.data()->addAction(tr("What's This?"));
+        if (p.data()->exec(e->globalPos()) == wt) {
             QHelpEvent e(QEvent::WhatsThis, w->rect().center(),
                          w->mapToGlobal(w->rect().center()));
             QApplication::sendEvent(w, &e);
         }
+        delete p.data();
     }
 #endif
 }
diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp
index d1b2e3f..ed437ff 100644
--- a/src/gui/dialogs/qmessagebox.cpp
+++ b/src/gui/dialogs/qmessagebox.cpp
@@ -92,8 +92,8 @@ public:
         {
 #ifndef QT_NO_CONTEXTMENU
             QMenu *menu = createStandardContextMenu();
-            menu->exec(e->globalPos());
-            delete menu;
+            menu->setAttribute(Qt::WA_DeleteOnClose);
+            menu->popup(e->globalPos());
 #else
             Q_UNUSED(e);
 #endif
diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp
index aaaa3ca..8d3923f 100644
--- a/src/gui/text/qtextcontrol.cpp
+++ b/src/gui/text/qtextcontrol.cpp
@@ -1762,8 +1762,8 @@ void QTextControlPrivate::contextMenuEvent(const QPoint &screenPos, const QPoint
     QMenu *menu = q->createStandardContextMenu(docPos, contextWidget);
     if (!menu)
         return;
-    menu->exec(screenPos);
-    delete menu;
+    menu->setAttribute(Qt::WA_DeleteOnClose);
+    menu->popup(screenPos);
 #endif
 }
 
diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp
index c779312..b81f04f 100644
--- a/src/gui/widgets/qlabel.cpp
+++ b/src/gui/widgets/qlabel.cpp
@@ -951,8 +951,8 @@ void QLabel::contextMenuEvent(QContextMenuEvent *ev)
         return;
     }
     ev->accept();
-    menu->exec(ev->globalPos());
-    delete menu;
+    menu->setAttribute(Qt::WA_DeleteOnClose);
+    menu->popup(ev->globalPos());
 #endif
 }
 
diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp
index 2d2df92..141f844 100644
--- a/src/gui/widgets/qlineedit.cpp
+++ b/src/gui/widgets/qlineedit.cpp
@@ -2046,9 +2046,9 @@ void QLineEdit::dropEvent(QDropEvent* e)
 */
 void QLineEdit::contextMenuEvent(QContextMenuEvent *event)
 {
-    QPointer<QMenu> menu = createStandardContextMenu();
-    menu->exec(event->globalPos());
-    delete menu;
+    QMenu *menu = createStandardContextMenu();
+    menu->setAttribute(Qt::WA_DeleteOnClose);
+    menu->popup(event->globalPos());
 }
 
 #if defined(Q_WS_WIN)
diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp
index eb25417..a63f3bf 100644
--- a/src/gui/widgets/qmainwindow.cpp
+++ b/src/gui/widgets/qmainwindow.cpp
@@ -1555,11 +1555,15 @@ void QMainWindow::contextMenuEvent(QContextMenuEvent *event)
 
 #ifndef QT_NO_MENU
     QMenu *popup = createPopupMenu();
-    if (popup && !popup->isEmpty()) {
-        popup->exec(event->globalPos());
-        event->accept();
+    if (popup) {
+        if (!popup->isEmpty()) {
+            popup->setAttribute(Qt::WA_DeleteOnClose);
+            popup->popup(event->globalPos());
+            event->accept();
+        } else {
+            delete popup;
+        }
     }
-    delete popup;
 #endif
 }
 #endif // QT_NO_CONTEXTMENU
diff --git a/tests/auto/qlabel/tst_qlabel.cpp b/tests/auto/qlabel/tst_qlabel.cpp
index 7099917..153149e7 100644
--- a/tests/auto/qlabel/tst_qlabel.cpp
+++ b/tests/auto/qlabel/tst_qlabel.cpp
@@ -121,6 +121,10 @@ private slots:
     void mnemonic();
     void selection();
 
+#ifndef QT_NO_CONTEXTMENU
+    void taskQTBUG_7902_contextMenuCrash();
+#endif
+
 private:
     QLabel *testWidget;
     QPointer<Widget> test_box;
@@ -582,5 +586,25 @@ void tst_QLabel::selection()
     QCOMPARE(label.selectionStart(), 6);
 }
 
+#ifndef QT_NO_CONTEXTMENU
+void tst_QLabel::taskQTBUG_7902_contextMenuCrash()
+{
+    QLabel *w = new QLabel("Test or crash?");
+    w->setTextInteractionFlags(Qt::TextSelectableByMouse);
+    w->show();
+    QTest::qWaitForWindowShown(w);
+
+    QTimer ti;
+    w->connect(&ti, SIGNAL(timeout()), w, SLOT(deleteLater()));
+    ti.start(300);
+
+    QContextMenuEvent *cme = new QContextMenuEvent(QContextMenuEvent::Mouse, w->rect().center());
+    qApp->postEvent(w, cme);
+
+    QTest::qWait(350);
+    // No crash, it's allright.
+}
+#endif
+
 QTEST_MAIN(tst_QLabel)
 #include "tst_qlabel.moc"
diff --git a/tests/auto/qlineedit/tst_qlineedit.cpp b/tests/auto/qlineedit/tst_qlineedit.cpp
index 7283916..fcca58a 100644
--- a/tests/auto/qlineedit/tst_qlineedit.cpp
+++ b/tests/auto/qlineedit/tst_qlineedit.cpp
@@ -271,6 +271,9 @@ private slots:
     void taskQTBUG_4401_enterKeyClearsPassword();
     void taskQTBUG_4679_moveToStartEndOfBlock();
     void taskQTBUG_4679_selectToStartEndOfBlock();
+#ifndef QT_NO_CONTEXTMENU
+    void taskQTBUG_7902_contextMenuCrash();
+#endif
 
 protected slots:
 #ifdef QT3_SUPPORT
@@ -3638,5 +3641,25 @@ void tst_QLineEdit::taskQTBUG_4679_selectToStartEndOfBlock()
 #endif // Q_OS_MAC
 }
 
+#ifndef QT_NO_CONTEXTMENU
+void tst_QLineEdit::taskQTBUG_7902_contextMenuCrash()
+{
+    // Would pass before the associated commit, but left as a guard.
+    QLineEdit *w = new QLineEdit;
+    w->show();
+    QTest::qWaitForWindowShown(w);
+
+    QTimer ti;
+    w->connect(&ti, SIGNAL(timeout()), w, SLOT(deleteLater()));
+    ti.start(200);
+
+    QContextMenuEvent *cme = new QContextMenuEvent(QContextMenuEvent::Mouse, w->rect().center());
+    qApp->postEvent(w, cme);
+
+    QTest::qWait(300);
+    // No crash, it's allright.
+}
+#endif
+
 QTEST_MAIN(tst_QLineEdit)
 #include "tst_qlineedit.moc"
diff --git a/tests/auto/qtextedit/tst_qtextedit.cpp b/tests/auto/qtextedit/tst_qtextedit.cpp
index deb9379..101baa5 100644
--- a/tests/auto/qtextedit/tst_qtextedit.cpp
+++ b/tests/auto/qtextedit/tst_qtextedit.cpp
@@ -201,6 +201,9 @@ private slots:
     void noWrapBackgrounds();
     void preserveCharFormatAfterUnchangingSetPosition();
     void twoSameInputMethodEvents();
+#ifndef QT_NO_CONTEXTMENU
+    void taskQTBUG_7902_contextMenuCrash();
+#endif
 
 private:
     void createSelection();
@@ -2202,5 +2205,24 @@ void tst_QTextEdit::twoSameInputMethodEvents()
     QCOMPARE(ed->document()->firstBlock().layout()->lineCount(), 1);
 }
 
+#ifndef QT_NO_CONTEXTMENU
+void tst_QTextEdit::taskQTBUG_7902_contextMenuCrash()
+{
+    QTextEdit *w = new QTextEdit;
+    w->show();
+    QTest::qWaitForWindowShown(w);
+
+    QTimer ti;
+    w->connect(&ti, SIGNAL(timeout()), w, SLOT(deleteLater()));
+    ti.start(200);
+
+    QContextMenuEvent *cme = new QContextMenuEvent(QContextMenuEvent::Mouse, w->rect().center());
+    qApp->postEvent(w->viewport(), cme);
+
+    QTest::qWait(300);
+    // No crash, it's allright.
+}
+#endif
+
 QTEST_MAIN(tst_QTextEdit)
 #include "tst_qtextedit.moc"
-- 
cgit v0.12


From 8b20c0ec6d676b3b297b8fa0ee436ad2e3d9a720 Mon Sep 17 00:00:00 2001
From: Gunnar Sletta <gunnar@trolltech.com>
Date: Wed, 10 Feb 2010 16:57:23 +0100
Subject: Added geometry shaders to changes-4.7.0 file + a small doc update
 about it

---
 dist/changes-4.7.0              | 3 +++
 src/opengl/qglshaderprogram.cpp | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/dist/changes-4.7.0 b/dist/changes-4.7.0
index 92f5244..3504763 100644
--- a/dist/changes-4.7.0
+++ b/dist/changes-4.7.0
@@ -24,6 +24,9 @@ General Improvements
 
 - Documentation and Examples
 
+- Support for the GL_EXT_geometry_shader4, aka Geometry Shaders, was added
+  to QGLShaderProgram. 
+
 Third party components
 ----------------------
 
diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp
index 8e256ab..170b650 100644
--- a/src/opengl/qglshaderprogram.cpp
+++ b/src/opengl/qglshaderprogram.cpp
@@ -143,6 +143,8 @@ QT_BEGIN_NAMESPACE
 
     \value Vertex Vertex shader written in the OpenGL Shading Language (GLSL).
     \value Fragment Fragment shader written in the OpenGL Shading Language (GLSL).
+    \value Geometry Geometry shaders written in the OpenGL Shading
+           Language (GLSL), based on the GL_EXT_geometry_shader4 extension.
 */
 
 #ifndef GL_FRAGMENT_SHADER
-- 
cgit v0.12