[gtk+] Handle non-baseline supporting subclasses overriding baseline supporting classes



commit 316d4504213689a9e81f010ad230a4ce86b17803
Author: Alexander Larsson <alexl redhat com>
Date:   Wed Mar 27 10:22:14 2013 +0100

    Handle non-baseline supporting subclasses overriding baseline supporting classes
    
    If a subclass (say a child of GtkButton) overrides the non-baseline
    size request methods we need to call these, rather than the new
    get_height_and_baseline_for_width method.
    
    In order to handle this we make the default for this method to be
    NULL, and instead check at runtime which method to call. If any
    non-baseline vfunc has changed in a class but the baseline one
    hasn't, then we can't use the baseline one.

 gtk/gtksizerequest.c   | 59 +++++++++++++++++++++++++++++++++++++++++++++-----
 gtk/gtkwidget.c        | 30 +++----------------------
 gtk/gtkwidgetprivate.h |  1 +
 3 files changed, 57 insertions(+), 33 deletions(-)
---
diff --git a/gtk/gtksizerequest.c b/gtk/gtksizerequest.c
index 4e47d88..26a7efc 100644
--- a/gtk/gtksizerequest.c
+++ b/gtk/gtksizerequest.c
@@ -93,6 +93,46 @@ get_vfunc_name (GtkOrientation orientation,
     return for_size < 0 ? "get_preferred_height" : "get_preferred_height_for_width";
 }
 
+static gboolean
+widget_class_has_baseline_support (GtkWidgetClass *widget_class)
+{
+  GtkWidgetClass *parent_class;
+
+  if (widget_class->get_preferred_height_and_baseline_for_width == NULL)
+    return FALSE;
+
+  /* This is kinda hacky, but for backwards compatibility reasons we have to handle the case
+     where a class previously did not support get_preferred_height_and_baseline_for_width,
+     but then gained support for it, and a subclass of it overrides the previous non-baseline
+     methods. If this happens we need to call the overridden (non-baseline supporting) versions
+     on the subclass, rather than the inherited but not overriddent new 
get_preferred_height_and_baseline_for_width.
+  */
+
+  /* Loop over all parent classes that inherit the same get_preferred_height_and_baseline_for_width */
+  parent_class = g_type_class_peek_parent (widget_class);
+  while (parent_class != NULL &&
+        parent_class->get_preferred_height_and_baseline_for_width == 
widget_class->get_preferred_height_and_baseline_for_width)
+    {
+      if (parent_class->get_preferred_height != widget_class->get_preferred_height ||
+         parent_class->get_preferred_height_for_width != widget_class->get_preferred_height_for_width)
+       return FALSE;
+
+       parent_class = g_type_class_peek_parent (parent_class);
+    }
+
+  return TRUE;
+}
+
+gboolean
+_gtk_widget_has_baseline_support (GtkWidget *widget)
+{
+  GtkWidgetClass *widget_class;
+
+  widget_class = GTK_WIDGET_GET_CLASS (widget);
+
+  return widget_class_has_baseline_support (widget_class);
+}
+
 static void
 gtk_widget_query_size_for_orientation (GtkWidget        *widget,
                                        GtkOrientation    orientation,
@@ -170,9 +210,12 @@ gtk_widget_query_size_for_orientation (GtkWidget        *widget,
           if (for_size < 0)
             {
              push_recursion_check (widget, orientation, for_size);
-             widget_class->get_preferred_height_and_baseline_for_width (widget, -1,
-                                                                        &min_size, &nat_size,
-                                                                        &min_baseline, &nat_baseline);
+             if (widget_class_has_baseline_support (widget_class))
+               widget_class->get_preferred_height_and_baseline_for_width (widget, -1,
+                                                                          &min_size, &nat_size,
+                                                                          &min_baseline, &nat_baseline);
+             else
+               widget_class->get_preferred_height (widget, &min_size, &nat_size);
              pop_recursion_check (widget, orientation);
             }
           else
@@ -194,9 +237,13 @@ gtk_widget_query_size_for_orientation (GtkWidget        *widget,
                                                    &adjusted_for_size);
 
              push_recursion_check (widget, orientation, for_size);
-             widget_class->get_preferred_height_and_baseline_for_width (widget, MAX (adjusted_for_size, 
minimum_width),
-                                                                        &min_size, &nat_size,
-                                                                        &min_baseline, &nat_baseline);
+             if (widget_class_has_baseline_support (widget_class))
+               widget_class->get_preferred_height_and_baseline_for_width (widget, MAX (adjusted_for_size, 
minimum_width),
+                                                                          &min_size, &nat_size,
+                                                                          &min_baseline, &nat_baseline);
+             else
+               widget_class->get_preferred_height_for_width (widget, MAX (adjusted_for_size, minimum_width),
+                                                             &min_size, &nat_size);
              pop_recursion_check (widget, orientation);
             }
         }
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 4ba5b71..f2f239f 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -799,12 +799,6 @@ static void             gtk_widget_real_get_width               (GtkWidget
 static void             gtk_widget_real_get_height              (GtkWidget         *widget,
                                                                  gint              *minimum_size,
                                                                  gint              *natural_size);
-static void  gtk_widget_real_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
-                                                                         gint       width,
-                                                                         gint      *minimum_height,
-                                                                         gint      *natural_height,
-                                                                         gint      *minimum_baseline,
-                                                                         gint      *natural_baseline);
 
 static void             gtk_widget_queue_tooltip_query          (GtkWidget *widget);
 
@@ -1124,7 +1118,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
   klass->get_preferred_height = gtk_widget_real_get_height;
   klass->get_preferred_width_for_height = gtk_widget_real_get_width_for_height;
   klass->get_preferred_height_for_width = gtk_widget_real_get_height_for_width;
-  klass->get_preferred_height_and_baseline_for_width = 
gtk_widget_real_get_preferred_height_and_baseline_for_width;
+  klass->get_preferred_height_and_baseline_for_width = NULL;
   klass->state_changed = NULL;
   klass->state_flags_changed = gtk_widget_real_state_flags_changed;
   klass->parent_set = NULL;
@@ -5417,7 +5411,8 @@ gtk_widget_size_allocate_with_baseline (GtkWidget     *widget,
   /* Never pass a baseline to a child unless it requested it.
      This means containers don't have to manually check for this. */
   if (baseline != -1 &&
-      gtk_widget_get_valign_with_baseline (widget) != GTK_ALIGN_BASELINE)
+      (gtk_widget_get_valign_with_baseline (widget) != GTK_ALIGN_BASELINE ||
+       !_gtk_widget_has_baseline_support (widget)))
     baseline = -1;
 
   alloc_needed = priv->alloc_needed;
@@ -13619,25 +13614,6 @@ gtk_widget_real_get_width_for_height (GtkWidget *widget,
   GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, minimum_width, natural_width);
 }
 
-static void
-gtk_widget_real_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
-                                                            gint       width,
-                                                            gint      *minimum_height,
-                                                            gint      *natural_height,
-                                                            gint      *minimum_baseline,
-                                                            gint      *natural_baseline)
-{
-  if (width == -1)
-    GTK_WIDGET_GET_CLASS (widget)->get_preferred_height (widget, minimum_height, natural_height);
-  else
-    GTK_WIDGET_GET_CLASS (widget)->get_preferred_height_for_width (widget, width, minimum_height, 
natural_height);
-
-  if (minimum_baseline)
-    *minimum_baseline = -1;
-  if (natural_baseline)
-    *natural_baseline = -1;
-}
-
 /**
  * gtk_widget_get_halign:
  * @widget: a #GtkWidget
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index 7927813..6ec03fd 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -77,6 +77,7 @@ void _gtk_widget_get_preferred_size_for_size   (GtkWidget         *widget,
                                                 gint               size,
                                                 gint              *minimum,
                                                 gint              *natural);
+gboolean _gtk_widget_has_baseline_support (GtkWidget *widget);
 
 gboolean _gtk_widget_get_translation_to_window (GtkWidget      *widget,
                                                 GdkWindow      *window,


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