[gtk+] GtkGLArea: Add resize signal



commit 37d0159a8497d229852a865ecc92a330dddd311e
Author: Alexander Larsson <alexl redhat com>
Date:   Thu Oct 30 19:49:43 2014 +0100

    GtkGLArea: Add resize signal
    
    This is very useful, as almost all GL code wants to recalculate
    the cameras each time the window size changes.

 gtk/gtkglarea.c |   68 ++++++++++++++++++++++++++++++++++++++++++++++--------
 gtk/gtkglarea.h |    3 ++
 2 files changed, 61 insertions(+), 10 deletions(-)
---
diff --git a/gtk/gtkglarea.c b/gtk/gtkglarea.c
index 49b2273..0c8788a 100644
--- a/gtk/gtkglarea.c
+++ b/gtk/gtkglarea.c
@@ -134,6 +134,7 @@ typedef struct {
   gboolean has_depth_buffer;
   gboolean has_stencil_buffer;
 
+  gboolean needs_resize;
   gboolean needs_render;
   gboolean auto_render;
 } GtkGLAreaPrivate;
@@ -156,6 +157,7 @@ static GParamSpec *obj_props[LAST_PROP] = { NULL, };
 
 enum {
   RENDER,
+  RESIZE,
 
   LAST_SIGNAL
 };
@@ -257,7 +259,8 @@ gtk_gl_area_get_property (GObject    *gobject,
 static void
 gtk_gl_area_realize (GtkWidget *widget)
 {
-  GtkGLAreaPrivate *priv = gtk_gl_area_get_instance_private ((GtkGLArea *) widget);
+  GtkGLArea *area = GTK_GL_AREA (widget);
+  GtkGLAreaPrivate *priv = gtk_gl_area_get_instance_private (area);
   GtkAllocation allocation;
   GdkWindowAttr attributes;
   gint attributes_mask;
@@ -281,6 +284,14 @@ gtk_gl_area_realize (GtkWidget *widget)
   priv->context = gdk_window_create_gl_context (gtk_widget_get_window (widget),
                                                priv->profile,
                                                &priv->error);
+
+  priv->needs_resize = TRUE;
+}
+
+static void
+gtk_gl_area_resize (GtkGLArea *area, int width, int height)
+{
+  glViewport (0, 0, width, height);
 }
 
 /*
@@ -539,13 +550,17 @@ gtk_gl_area_size_allocate (GtkWidget     *widget,
 
   GTK_WIDGET_CLASS (gtk_gl_area_parent_class)->size_allocate (widget, allocation);
 
-  if (gtk_widget_get_realized (widget) &&
-      priv->event_window != NULL)
-    gdk_window_move_resize (priv->event_window,
-                           allocation->x,
-                           allocation->y,
-                           allocation->width,
-                           allocation->height);
+  if (gtk_widget_get_realized (widget))
+    {
+      if (priv->event_window != NULL)
+       gdk_window_move_resize (priv->event_window,
+                               allocation->x,
+                               allocation->y,
+                               allocation->width,
+                               allocation->height);
+
+      priv->needs_resize = TRUE;
+    }
 
   priv->needs_render = TRUE;
   gtk_gl_area_maybe_allocate_buffers (area);
@@ -605,15 +620,21 @@ gtk_gl_area_draw (GtkWidget *widget,
   scale = gtk_widget_get_scale_factor (widget);
   w = gtk_widget_get_allocated_width (widget) * scale;
   h = gtk_widget_get_allocated_height (widget) * scale;
- 
+
   status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
   if (status ==  GL_FRAMEBUFFER_COMPLETE_EXT)
     {
       if (priv->needs_render || priv->auto_render)
        {
-         glViewport(0, 0, w, h);
+         if (priv->needs_resize)
+           {
+             g_signal_emit (area, area_signals[RESIZE], 0, w, h, NULL);
+             priv->needs_resize = FALSE;
+           }
+
          g_signal_emit (area, area_signals[RENDER], 0, priv->context, &unused);
        }
+
       priv->needs_render = FALSE;
 
       gdk_cairo_draw_from_gl (cr,
@@ -638,6 +659,8 @@ gtk_gl_area_class_init (GtkGLAreaClass *klass)
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
+  klass->resize = gtk_gl_area_resize;
+
   widget_class->realize = gtk_gl_area_realize;
   widget_class->unrealize = gtk_gl_area_unrealize;
   widget_class->map = gtk_gl_area_map;
@@ -783,6 +806,31 @@ gtk_gl_area_class_init (GtkGLAreaClass *klass)
                    NULL,
                   G_TYPE_BOOLEAN, 1,
                   GDK_TYPE_GL_CONTEXT);
+
+  /**
+   * GtkGLArea::resized:
+   * @area: the #GtkGLArea that emitted the signal
+   *
+   * The ::resized signal is emitted once when the widget is realized, and
+   * then each time the widget is changed while realized. This is useful
+   * in order to keep GL state up to date with the widget size, like for
+   * instance camera properties which may depend on the width/height ratio.
+   *
+   * The GL context for the area is guaranteed to be current when this is emitted.
+   *
+   * The default handler sets up the gl Viewport.
+   *
+   * Since: 3.16
+   */
+  area_signals[RESIZE] =
+    g_signal_new ("resize",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GtkGLAreaClass, resize),
+                  NULL, NULL,
+                  _gtk_marshal_VOID__INT_INT,
+                  G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
+
 }
 
 static void
diff --git a/gtk/gtkglarea.h b/gtk/gtkglarea.h
index 87fb453..f3ad2a1 100644
--- a/gtk/gtkglarea.h
+++ b/gtk/gtkglarea.h
@@ -68,6 +68,9 @@ struct _GtkGLAreaClass
   /*< public >*/
   gboolean       (* render)         (GtkGLArea        *area,
                                      GdkGLContext     *context);
+  void           (* resize)         (GtkGLArea        *area,
+                                    int               width,
+                                    int               height);
 
   /*< private >*/
   gpointer _padding[6];


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]