[gtk/wip/otte/snapshot] widgetpaintable: Protect against too many signals



commit f16f67f750e0c2c59f6f016c7b39612bd56b528f
Author: Benjamin Otte <otte redhat com>
Date:   Sun Apr 1 15:25:16 2018 +0200

    widgetpaintable: Protect against too many signals
    
    This is actually not just a mechnaism to protect against too many
    signals, but it's also a method to getting those signals at the wrong
    time.
    
    For every size/content change, a widget needs to invalidate twice:
    Once when it queues a resize/redraw (going valid => invalid) and once
    when the new size/content is actually assigned (going invalid => valid).
    
    However, one of those invalidations might be inconvenient for the
    listener. GtkImage for example does not like receiving
    invalidate-contents signals when new contents are assigned, but is fine
    with them when the old ones go invalid. And it will not try to draw the
    paintable in between anyway.
    
    So by bypassing the 2nd emission if nothing was changed, we can make
    GtkImage happy.

 gtk/gtkwidget.c                 |  8 +++++---
 gtk/gtkwidgetpaintable.c        | 34 +++++++++++++++++++++++++++++++++-
 gtk/gtkwidgetpaintableprivate.h | 30 ++++++++++++++++++++++++++++++
 3 files changed, 68 insertions(+), 4 deletions(-)
---
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 3e20d79282..44ce62e791 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -64,7 +64,7 @@
 #include "gtktooltipprivate.h"
 #include "gtktypebuiltins.h"
 #include "gtkversion.h"
-#include "gtkwidgetpaintable.h"
+#include "gtkwidgetpaintableprivate.h"
 #include "gtkwidgetpathprivate.h"
 #include "gtkwindowgroup.h"
 #include "gtkwindowprivate.h"
@@ -3978,7 +3978,7 @@ gtk_widget_invalidate_paintable_contents (GtkWidget *widget)
     return;
 
   for (l = priv->paintables; l; l = l->next)
-    gdk_paintable_invalidate_contents (l->data);
+    gtk_widget_paintable_invalidate_contents (l->data);
 }
 
 static void
@@ -3988,7 +3988,7 @@ gtk_widget_invalidate_paintable_size (GtkWidget *widget)
   GSList *l;
 
   for (l = priv->paintables; l; l = l->next)
-    gdk_paintable_invalidate_size (l->data);
+    gtk_widget_paintable_invalidate_size (l->data);
 }
 
 /**
@@ -4472,6 +4472,8 @@ gtk_widget_size_allocate (GtkWidget           *widget,
   priv->alloc_needed = FALSE;
   priv->alloc_needed_on_child = FALSE;
 
+  gtk_widget_invalidate_paintable_size (widget);
+
 check_clip:
   if (position_changed || size_changed || baseline_changed)
     gtk_widget_queue_draw (widget);
diff --git a/gtk/gtkwidgetpaintable.c b/gtk/gtkwidgetpaintable.c
index be167d6005..948beb1b23 100644
--- a/gtk/gtkwidgetpaintable.c
+++ b/gtk/gtkwidgetpaintable.c
@@ -19,7 +19,7 @@
 
 #include "config.h"
 
-#include "gtkwidgetpaintable.h"
+#include "gtkwidgetpaintableprivate.h"
 
 #include "gtkintl.h"
 #include "gtksnapshot.h"
@@ -59,6 +59,9 @@ struct _GtkWidgetPaintable
 
   GtkWidget *widget;
   guint loop_tracker;
+
+  guint size_invalid : 1;
+  guint contents_invalid : 1;
 };
 
 struct _GtkWidgetPaintableClass
@@ -84,6 +87,8 @@ gtk_widget_paintable_paintable_snapshot (GdkPaintable *paintable,
   GtkWidgetPaintable *self = GTK_WIDGET_PAINTABLE (paintable);
   graphene_matrix_t transform;
 
+  self->contents_invalid = FALSE;
+
   if (self->widget == NULL ||
       !_gtk_widget_is_drawable (self->widget) ||
       _gtk_widget_get_alloc_needed (self->widget))
@@ -119,6 +124,11 @@ gtk_widget_paintable_paintable_snapshot (GdkPaintable *paintable,
 static GdkPaintable *
 gtk_widget_paintable_paintable_get_current_image (GdkPaintable *paintable)
 {
+  GtkWidgetPaintable *self = GTK_WIDGET_PAINTABLE (paintable);
+
+  self->contents_invalid = FALSE;
+  self->size_invalid = FALSE;
+
   g_warning ("FIXME: Implement once we can create paintables from render nodes");
 
   return NULL;
@@ -129,6 +139,8 @@ gtk_widget_paintable_paintable_get_intrinsic_width (GdkPaintable *paintable)
 {
   GtkWidgetPaintable *self = GTK_WIDGET_PAINTABLE (paintable);
 
+  self->size_invalid = FALSE;
+
   if (self->widget == NULL)
     return 0;
 
@@ -140,6 +152,8 @@ gtk_widget_paintable_paintable_get_intrinsic_height (GdkPaintable *paintable)
 {
   GtkWidgetPaintable *self = GTK_WIDGET_PAINTABLE (paintable);
 
+  self->size_invalid = FALSE;
+
   if (self->widget == NULL)
     return 0;
 
@@ -314,4 +328,22 @@ gtk_widget_paintable_set_widget (GtkWidgetPaintable *self,
   gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
 }
 
+void
+gtk_widget_paintable_invalidate_size (GtkWidgetPaintable *self)
+{
+  if (self->size_invalid)
+    return;
 
+  self->size_invalid = TRUE;
+  gdk_paintable_invalidate_size (GDK_PAINTABLE (self));
+}
+
+void
+gtk_widget_paintable_invalidate_contents (GtkWidgetPaintable *self)
+{
+  if (self->contents_invalid)
+    return;
+
+  self->contents_invalid = TRUE;
+  gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
+}
diff --git a/gtk/gtkwidgetpaintableprivate.h b/gtk/gtkwidgetpaintableprivate.h
new file mode 100644
index 0000000000..c5abc0146e
--- /dev/null
+++ b/gtk/gtkwidgetpaintableprivate.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2018 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#ifndef __GTK_WIDGET_PAINTABLE_PRIVATE_H__
+#define __GTK_WIDGET_PAINTABLE_PRIVATE_H__
+
+#include "gtkwidgetpaintable.h"
+
+
+void            gtk_widget_paintable_invalidate_size            (GtkWidgetPaintable     *self);
+void            gtk_widget_paintable_invalidate_contents        (GtkWidgetPaintable     *self);
+
+
+#endif /* __GTK_WIDGET_PAINTABLE_PRIVATE_H__ */


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