]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkwidget.c
GtkCellAreaBoxPrivate: Improve struct packing
[~andy/gtk] / gtk / gtkwidget.c
index 0b5f9264a5139140e152dbe0c9806ac46f3d95c4..b3cb3a9c96c21bd7079c70af0694960d3d48def7 100644 (file)
  * </refsect2>
  */
 
+/* Add flags here that should not be propagated to children. By default,
+ * all flags will be set on children (think prelight or active), but we
+ * might want to not do this for some.
+ */
+#define GTK_STATE_FLAGS_DONT_PROPAGATE (GTK_STATE_FLAG_FOCUSED)
+#define GTK_STATE_FLAGS_DO_PROPAGATE (~GTK_STATE_FLAGS_DONT_PROPAGATE)
+
 #define WIDGET_CLASS(w)         GTK_WIDGET_GET_CLASS (w)
 #define        INIT_PATH_SIZE  (512)
 
@@ -321,7 +328,6 @@ struct _GtkWidgetPrivate
   guint mapped                : 1;
   guint visible               : 1;
   guint sensitive             : 1;
-  guint parent_sensitive      : 1;
   guint can_focus             : 1;
   guint has_focus             : 1;
   guint can_default           : 1;
@@ -524,7 +530,6 @@ struct _GtkStateData
 {
   guint         flags : 6;
   guint         operation : 2;
-  guint         parent_sensitive : 1;
   guint                use_forall : 1;
 };
 
@@ -3514,7 +3519,6 @@ gtk_widget_init (GtkWidget *widget)
   priv->parent = NULL;
 
   priv->sensitive = TRUE;
-  priv->parent_sensitive = TRUE;
   priv->composite_child = composite_child_stack != 0;
   priv->double_buffered = TRUE;
   priv->redraw_on_alloc = TRUE;
@@ -4478,8 +4482,8 @@ gtk_widget_unrealize (GtkWidget *widget)
  * Since: 3.0
  **/
 void
-gtk_widget_queue_draw_region (GtkWidget      *widget,
-                              cairo_region_t *region)
+gtk_widget_queue_draw_region (GtkWidget            *widget,
+                              const cairo_region_t *region)
 {
   GtkWidgetPrivate *priv;
   GtkWidget *w;
@@ -5115,11 +5119,27 @@ gtk_widget_real_size_allocate (GtkWidget     *widget,
      }
 }
 
+/* translate initial/final into start/end */
+static GtkAlign
+effective_align (GtkAlign         align,
+                 GtkTextDirection direction)
+{
+  switch (align)
+    {
+    case GTK_ALIGN_START:
+      return direction == GTK_TEXT_DIR_RTL ? GTK_ALIGN_END : GTK_ALIGN_START;
+    case GTK_ALIGN_END:
+      return direction == GTK_TEXT_DIR_RTL ? GTK_ALIGN_START : GTK_ALIGN_END;
+    default:
+      return align;
+    }
+}
+
 static void
-adjust_for_align(GtkAlign           align,
-                 gint              *natural_size,
-                 gint              *allocated_pos,
-                 gint              *allocated_size)
+adjust_for_align (GtkAlign  align,
+                  gint     *natural_size,
+                  gint     *allocated_pos,
+                  gint     *allocated_size)
 {
   switch (align)
     {
@@ -5177,18 +5197,18 @@ gtk_widget_real_adjust_size_allocation (GtkWidget         *widget,
     {
       adjust_for_margin (aux_info->margin.left,
                          aux_info->margin.right,
-                         minimum_size, natural_size, 
-                        allocated_pos, allocated_size);
-      adjust_for_align (aux_info->halign,
+                         minimum_size, natural_size,
+                         allocated_pos, allocated_size);
+      adjust_for_align (effective_align (aux_info->halign, gtk_widget_get_direction (widget)),
                         natural_size, allocated_pos, allocated_size);
     }
   else
     {
       adjust_for_margin (aux_info->margin.top,
                          aux_info->margin.bottom,
-                         minimum_size, natural_size, 
-                        allocated_pos, allocated_size);
-      adjust_for_align (aux_info->valign,
+                         minimum_size, natural_size,
+                         allocated_pos, allocated_size);
+      adjust_for_align (effective_align (aux_info->valign, GTK_TEXT_DIR_NONE),
                         natural_size, allocated_pos, allocated_size);
     }
 }
@@ -6468,7 +6488,10 @@ gtk_widget_real_query_tooltip (GtkWidget  *widget,
 static void
 gtk_widget_real_style_updated (GtkWidget *widget)
 {
-  if (gtk_widget_get_realized (widget))
+  GtkWidgetPrivate *priv = widget->priv;
+
+  if (priv->style != NULL &&
+      priv->style != gtk_widget_get_default_style ())
     {
       /* Trigger ::style-set for old
        * widgets not listening to this
@@ -6481,8 +6504,6 @@ gtk_widget_real_style_updated (GtkWidget *widget)
 
   if (widget->priv->context)
     {
-      gtk_style_context_invalidate (widget->priv->context);
-
       if (gtk_widget_get_realized (widget) &&
           gtk_widget_get_has_window (widget))
         gtk_style_context_set_background (widget->priv->context,
@@ -6920,17 +6941,7 @@ gtk_widget_set_name (GtkWidget    *widget,
   g_free (priv->name);
   priv->name = new_name;
 
-  if (priv->path)
-    {
-      guint pos;
-
-      pos = gtk_widget_path_length (priv->path) - 1;
-      gtk_widget_path_iter_set_name (priv->path, pos,
-                                     priv->name);
-    }
-
-  if (priv->context)
-    gtk_style_context_set_path (priv->context, priv->path);
+  gtk_widget_reset_style (widget);
 
   g_object_notify (G_OBJECT (widget), "name");
 }
@@ -6990,11 +7001,6 @@ _gtk_widget_update_state_flags (GtkWidget     *widget,
       data.operation = operation;
       data.use_forall = FALSE;
 
-      if (priv->parent)
-       data.parent_sensitive = (gtk_widget_is_sensitive (priv->parent) != FALSE);
-      else
-       data.parent_sensitive = TRUE;
-
       gtk_widget_propagate_state (widget, &data);
 
       gtk_widget_queue_resize (widget);
@@ -7081,9 +7087,6 @@ gtk_widget_get_state_flags (GtkWidget *widget)
 
   flags = widget->priv->state_flags;
 
-  if (!gtk_widget_is_sensitive (widget))
-    flags |= GTK_STATE_FLAG_INSENSITIVE;
-
   if (gtk_widget_has_focus (widget))
     flags |= GTK_STATE_FLAG_FOCUSED;
 
@@ -7593,11 +7596,6 @@ gtk_widget_set_sensitive (GtkWidget *widget,
 
   data.use_forall = TRUE;
 
-  if (priv->parent)
-    data.parent_sensitive = gtk_widget_is_sensitive (priv->parent);
-  else
-    data.parent_sensitive = TRUE;
-
   gtk_widget_propagate_state (widget, &data);
 
   gtk_widget_queue_resize (widget);
@@ -7632,7 +7630,7 @@ gtk_widget_get_sensitive (GtkWidget *widget)
  * @widget: a #GtkWidget
  *
  * Returns the widget's effective sensitivity, which means
- * it is sensitive itself and also its parent widget is sensntive
+ * it is sensitive itself and also its parent widget is sensitive
  *
  * Returns: %TRUE if the widget is effectively sensitive
  *
@@ -7643,7 +7641,7 @@ gtk_widget_is_sensitive (GtkWidget *widget)
 {
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
-  return widget->priv->sensitive && widget->priv->parent_sensitive;
+  return !(widget->priv->state_flags & GTK_STATE_FLAG_INSENSITIVE);
 }
 
 static void
@@ -7707,17 +7705,15 @@ gtk_widget_set_parent (GtkWidget *widget,
   parent_flags = gtk_widget_get_state_flags (parent);
 
   /* Merge both old state and current parent state,
-   * We don't want the insensitive flag to propagate
-   * to the new child though */
-  data.flags = parent_flags & ~GTK_STATE_FLAG_INSENSITIVE;
+   * making sure to only propagate the right states */
+  data.flags = parent_flags & GTK_STATE_FLAGS_DO_PROPAGATE;
   data.flags |= priv->state_flags;
 
   data.operation = STATE_CHANGE_REPLACE;
-  data.parent_sensitive = (gtk_widget_is_sensitive (parent) != FALSE);
   data.use_forall = gtk_widget_is_sensitive (parent) != gtk_widget_is_sensitive (widget);
   gtk_widget_propagate_state (widget, &data);
 
-  gtk_widget_reset_rc_styles (widget);
+  gtk_widget_reset_style (widget);
 
   g_signal_emit (widget, widget_signals[PARENT_SET], 0, NULL);
   if (priv->parent->priv->anchored)
@@ -7757,19 +7753,6 @@ gtk_widget_set_parent (GtkWidget *widget,
       gtk_widget_queue_compute_expand (parent);
     }
 
-  if (widget->priv->context)
-    {
-      GdkScreen *screen;
-
-      _gtk_widget_update_path (widget);
-      gtk_style_context_set_path (widget->priv->context, widget->priv->path);
-
-      screen = gtk_widget_get_screen (widget);
-
-      if (screen)
-        gtk_style_context_set_screen (widget->priv->context, screen);
-    }
-
   gtk_widget_pop_verify_invariants (widget);
 }
 
@@ -7817,14 +7800,8 @@ gtk_widget_get_parent (GtkWidget *widget)
 void
 gtk_widget_style_attach (GtkWidget *widget)
 {
-  GtkWidgetPrivate *priv;
-
   g_return_if_fail (GTK_IS_WIDGET (widget));
   g_return_if_fail (gtk_widget_get_realized (widget));
-
-  priv = widget->priv;
-
-  priv->style = gtk_style_attach (priv->style, priv->window);
 }
 
 /**
@@ -7855,11 +7832,8 @@ gtk_widget_has_rc_style (GtkWidget *widget)
  *     of a previous call to gtk_widget_set_style() and go back to
  *     the default style
  *
- * Sets the #GtkStyle for a widget (@widget->style).
- *
- * You probably don't want to use this function; it interacts
- * badly with themes, because themes work by replacing the #GtkStyle.
- * Instead, use gtk_widget_modify_style().
+ * Used to set the #GtkStyle for a widget (@widget->style). Since
+ * GTK 3, this function does nothing, the passed in style is ignored.
  *
  * Deprecated:3.0: Use #GtkStyleContext instead
  */
@@ -7885,27 +7859,21 @@ gtk_widget_set_style (GtkWidget *widget,
 void
 gtk_widget_ensure_style (GtkWidget *widget)
 {
-  g_return_if_fail (GTK_IS_WIDGET (widget));
+  GtkWidgetPrivate *priv;
 
-  if (!widget->priv->style ||
-      widget->priv->style == gtk_widget_get_default_style ())
-    {
-      GtkStyle *style;
+  g_return_if_fail (GTK_IS_WIDGET (widget));
 
-      if (widget->priv->style)
-        g_object_unref (widget->priv->style);
+  priv = widget->priv;
 
-      style = g_object_new (GTK_TYPE_STYLE,
-                            "context", gtk_widget_get_style_context (widget),
-                            NULL);
+  if (priv->style == gtk_widget_get_default_style ())
+    {
+      g_object_unref (priv->style);
 
-      widget->priv->style = g_object_ref (style);
+      priv->style = NULL;
 
       g_signal_emit (widget,
                      widget_signals[STYLE_SET],
                      0, NULL);
-
-      g_object_unref (style);
     }
 }
 
@@ -7922,9 +7890,21 @@ gtk_widget_ensure_style (GtkWidget *widget)
 GtkStyle*
 gtk_widget_get_style (GtkWidget *widget)
 {
+  GtkWidgetPrivate *priv;
+
   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
 
-  return widget->priv->style;
+  priv = widget->priv;
+
+  if (priv->style == NULL)
+    {
+      priv->style = g_object_new (GTK_TYPE_STYLE,
+                                  "context", gtk_widget_get_style_context (widget),
+                                  NULL);
+
+    }
+
+  return priv->style;
 }
 
 /**
@@ -8539,7 +8519,7 @@ do_screen_change (GtkWidget *widget,
 {
   if (old_screen != new_screen)
     {
-      GtkStyleContext *context;
+      GtkWidgetPrivate *priv = widget->priv;
 
       if (old_screen)
        {
@@ -8550,8 +8530,8 @@ do_screen_change (GtkWidget *widget,
 
       _gtk_tooltip_hide (widget);
 
-      context = gtk_widget_get_style_context (widget);
-      gtk_style_context_set_screen (context, gtk_widget_get_screen (widget));
+      if (new_screen && priv->context)
+        gtk_style_context_set_screen (priv->context, new_screen);
 
       g_signal_emit (widget, widget_signals[SCREEN_CHANGED], 0, old_screen);
     }
@@ -8718,12 +8698,7 @@ _gtk_widget_propagate_screen_changed (GtkWidget    *widget,
 static void
 reset_style_recurse (GtkWidget *widget, gpointer data)
 {
-  if (widget->priv->context)
-    {
-      _gtk_widget_update_path (widget);
-      gtk_style_context_set_path (widget->priv->context,
-                                  widget->priv->path);
-    }
+  _gtk_widget_update_path (widget);
 
   if (GTK_IS_CONTAINER (widget))
     gtk_container_forall (GTK_CONTAINER (widget),
@@ -9214,6 +9189,8 @@ gtk_widget_render_icon (GtkWidget      *widget,
                         GtkIconSize     size,
                         const gchar    *detail)
 {
+  gtk_widget_ensure_style (widget);
+
   return gtk_widget_render_icon_pixbuf (widget, stock_id, size);
 }
 
@@ -10635,7 +10612,8 @@ gtk_widget_real_destroy (GtkWidget *object)
 
   gtk_grab_remove (widget);
 
-  g_object_unref (priv->style);
+  if (priv->style)
+    g_object_unref (priv->style);
   priv->style = gtk_widget_get_default_style ();
   g_object_ref (priv->style);
 }
@@ -10669,6 +10647,8 @@ gtk_widget_finalize (GObject *object)
   if (priv->context)
     g_object_unref (priv->context);
 
+  _gtk_widget_free_cached_sizes (widget);
+
   if (g_object_is_floating (object))
     g_warning ("A floating object was finalized. This means that someone\n"
                "called g_object_unref() on an object that had only a floating\n"
@@ -10745,7 +10725,6 @@ gtk_widget_real_realize (GtkWidget *widget)
       priv->window = gtk_widget_get_parent_window (widget);
       g_object_ref (priv->window);
     }
-  priv->style = gtk_style_attach (priv->style, priv->window);
 }
 
 /*****************************************
@@ -10777,7 +10756,6 @@ gtk_widget_real_unrealize (GtkWidget *widget)
                          (GtkCallback) gtk_widget_unrealize,
                          NULL);
 
-  gtk_style_detach (priv->style);
   if (gtk_widget_get_has_window (widget))
     {
       gdk_window_set_user_data (priv->window, NULL);
@@ -11189,11 +11167,6 @@ gtk_widget_propagate_state (GtkWidget    *widget,
 
   old_state = gtk_widget_get_state (widget);
 
-  if (!priv->parent_sensitive)
-    old_flags |= GTK_STATE_FLAG_INSENSITIVE;
-
-  priv->parent_sensitive = data->parent_sensitive;
-
   switch (data->operation)
     {
     case STATE_CHANGE_REPLACE:
@@ -11207,6 +11180,10 @@ gtk_widget_propagate_state (GtkWidget    *widget,
       break;
     }
 
+  /* make insensitivity unoverridable */
+  if (!priv->sensitive)
+    priv->state_flags |= GTK_STATE_FLAG_INSENSITIVE;
+
   if (gtk_widget_is_focus (widget) && !gtk_widget_is_sensitive (widget))
     {
       GtkWidget *window;
@@ -11217,7 +11194,7 @@ gtk_widget_propagate_state (GtkWidget    *widget,
         gtk_window_set_focus (GTK_WINDOW (window), NULL);
     }
 
-  new_flags = gtk_widget_get_state_flags (widget);
+  new_flags = priv->state_flags;
 
   if (old_flags != new_flags)
     {
@@ -11267,19 +11244,19 @@ gtk_widget_propagate_state (GtkWidget    *widget,
 
       if (GTK_IS_CONTAINER (widget))
         {
-          data->parent_sensitive = gtk_widget_is_sensitive (widget);
+          GtkStateData child_data = *data;
 
-          /* Do not propagate focused state further */
-          data->flags &= ~GTK_STATE_FLAG_FOCUSED;
+          /* Make sure to only propate the right states further */
+          child_data.flags &= GTK_STATE_FLAGS_DO_PROPAGATE;
 
-          if (data->use_forall)
+          if (child_data.use_forall)
             gtk_container_forall (GTK_CONTAINER (widget),
                                   (GtkCallback) gtk_widget_propagate_state,
-                                  data);
+                                  &child_data);
           else
             gtk_container_foreach (GTK_CONTAINER (widget),
                                    (GtkCallback) gtk_widget_propagate_state,
-                                   data);
+                                   &child_data);
         }
 
       /* Trigger state change transitions for the widget */
@@ -13005,8 +12982,8 @@ gtk_widget_buildable_custom_finished (GtkBuildable *buildable,
 static GtkSizeRequestMode 
 gtk_widget_real_get_request_mode (GtkWidget *widget)
 { 
-  /* By default widgets are height-for-width. */
-  return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
+  /* By default widgets dont trade size at all. */
+  return GTK_SIZE_REQUEST_CONSTANT_SIZE;
 }
 
 static void
@@ -14336,15 +14313,23 @@ style_context_changed (GtkStyleContext *context,
 GtkStyleContext *
 gtk_widget_get_style_context (GtkWidget *widget)
 {
+  GtkWidgetPrivate *priv;
+  GtkWidgetPath *path;
+
   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
 
-  if (G_UNLIKELY (!widget->priv->context))
+  priv = widget->priv;
+  
+  /* updates style context if it exists already */
+  path = gtk_widget_get_path (widget);
+
+  if (G_UNLIKELY (priv->context == NULL))
     {
       GdkScreen *screen;
 
-      widget->priv->context = g_object_new (GTK_TYPE_STYLE_CONTEXT,
-                                            "direction", gtk_widget_get_direction (widget),
-                                            NULL);
+      priv->context = g_object_new (GTK_TYPE_STYLE_CONTEXT,
+                                    "direction", gtk_widget_get_direction (widget),
+                                    NULL);
 
       g_signal_connect (widget->priv->context, "changed",
                         G_CALLBACK (style_context_changed), widget);
@@ -14352,18 +14337,9 @@ gtk_widget_get_style_context (GtkWidget *widget)
       screen = gtk_widget_get_screen (widget);
 
       if (screen)
-        gtk_style_context_set_screen (widget->priv->context, screen);
+        gtk_style_context_set_screen (priv->context, screen);
 
-      _gtk_widget_update_path (widget);
-      gtk_style_context_set_path (widget->priv->context,
-                                  widget->priv->path);
-    }
-  else
-    {
-      /* Force widget path regeneration if needed, the
-       * context will be updated within this function.
-       */
-      gtk_widget_get_path (widget);
+      gtk_style_context_set_path (priv->context, path);
     }
 
   return widget->priv->context;