From 37d0159a8497d229852a865ecc92a330dddd311e Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 30 Oct 2014 19:49:43 +0100 Subject: [PATCH] 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 49b2273b76..0c8788a1d5 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 87fb453c72..f3ad2a1056 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];