]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkwidget.c
Merge branch 'native-layout-incubator'
[~andy/gtk] / gtk / gtkwidget.c
index 57cf079c795665d60c910858cbda16ac6fbf2ef4..982c85ba667a560b7bfc9753d9a39984fe084419 100644 (file)
@@ -53,6 +53,7 @@
 #include "gtkinvisible.h"
 #include "gtkbuildable.h"
 #include "gtkbuilderprivate.h"
+#include "gtkextendedlayout.h"
 #include "gtkalias.h"
 
 /**
@@ -62,6 +63,7 @@
  *
  * GtkWidget is the base class all widgets in GTK+ derive from. It manages the
  * widget lifecycle, states and style.
+ *
  * <refsect2 id="style-properties">
  * <para>
  * <structname>GtkWidget</structname> introduces <firstterm>style
@@ -343,6 +345,14 @@ static void             gtk_widget_buildable_custom_finished    (GtkBuildable
 static void             gtk_widget_buildable_parser_finished    (GtkBuildable     *buildable,
                                                                  GtkBuilder       *builder);
 
+static void             gtk_widget_extended_layout_init         (GtkExtendedLayoutIface *iface);
+static void             gtk_widget_real_get_desired_width       (GtkExtendedLayout *layout,
+                                                                 gint              *minimum_size,
+                                                                 gint              *natural_size);
+static void             gtk_widget_real_get_desired_height      (GtkExtendedLayout *layout,
+                                                                 gint              *minimum_size,
+                                                                 gint              *natural_size);
+
 static void             gtk_widget_queue_tooltip_query          (GtkWidget *widget);
      
 static void gtk_widget_set_usize_internal (GtkWidget *widget,
@@ -418,6 +428,13 @@ gtk_widget_get_type (void)
        NULL /* interface data */
       };
 
+      const GInterfaceInfo layout_info =
+      {
+       (GInterfaceInitFunc) gtk_widget_extended_layout_init,
+       (GInterfaceFinalizeFunc) NULL,
+       NULL /* interface data */
+      };
+
       widget_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkWidget",
                                            &widget_info, G_TYPE_FLAG_ABSTRACT);
 
@@ -425,7 +442,8 @@ gtk_widget_get_type (void)
                                    &accessibility_info) ;
       g_type_add_interface_static (widget_type, GTK_TYPE_BUILDABLE,
                                    &buildable_info) ;
-
+      g_type_add_interface_static (widget_type, GTK_TYPE_EXTENDED_LAYOUT,
+                                   &layout_info) ;
     }
 
   return widget_type;
@@ -2767,7 +2785,7 @@ gtk_widget_get_property (GObject         *object,
       g_value_set_boolean (value, (gtk_widget_get_receives_default (widget) != FALSE));
       break;
     case PROP_COMPOSITE_CHILD:
-      g_value_set_boolean (value, (GTK_WIDGET_FLAGS (widget) & GTK_COMPOSITE_CHILD) != 0 );
+      g_value_set_boolean (value, (GTK_OBJECT_FLAGS (widget) & GTK_COMPOSITE_CHILD) != 0 );
       break;
     case PROP_STYLE:
       g_value_set_object (value, gtk_widget_get_style (widget));
@@ -2794,8 +2812,7 @@ gtk_widget_get_property (GObject         *object,
         if (escaped && !pango_parse_markup (escaped, -1, 0, NULL, &text, NULL, NULL))
           g_assert (NULL == text); /* text should still be NULL in case of markup errors */
 
-        g_value_set_string (value, text);
-        g_free (text);
+        g_value_take_string (value, text);
       }
       break;
     case PROP_TOOLTIP_MARKUP:
@@ -2836,6 +2853,8 @@ gtk_widget_init (GtkWidget *widget)
 
   GTK_PRIVATE_SET_FLAG (widget, GTK_REDRAW_ON_ALLOC);
   GTK_PRIVATE_SET_FLAG (widget, GTK_REQUEST_NEEDED);
+  GTK_PRIVATE_SET_FLAG (widget, GTK_WIDTH_REQUEST_NEEDED);
+  GTK_PRIVATE_SET_FLAG (widget, GTK_HEIGHT_REQUEST_NEEDED);
   GTK_PRIVATE_SET_FLAG (widget, GTK_ALLOC_NEEDED);
 
   widget->style = gtk_widget_get_default_style ();
@@ -3862,7 +3881,7 @@ gtk_widget_draw (GtkWidget          *widget,
  * Also remember that the size request is not necessarily the size
  * a widget will actually be allocated.
  *
- * See also gtk_widget_get_child_requisition().
+ * Deprecated: 3.0: Use gtk_extended_layout_get_desired_size() instead.
  **/
 void
 gtk_widget_size_request (GtkWidget     *widget,
@@ -3872,10 +3891,11 @@ gtk_widget_size_request (GtkWidget      *widget,
 
 #ifdef G_ENABLE_DEBUG
   if (requisition == &widget->requisition)
-    g_warning ("gtk_widget_size_request() called on child widget with request equal\n to widget->requisition. gtk_widget_set_usize() may not work properly.");
+    g_warning ("gtk_widget_size_request() called on child widget with request equal\n"
+               "to widget->requisition. gtk_widget_set_usize() may not work properly.");
 #endif /* G_ENABLE_DEBUG */
 
-  _gtk_size_group_compute_requisition (widget, requisition);
+  gtk_extended_layout_get_desired_size (GTK_EXTENDED_LAYOUT (widget), FALSE, requisition, NULL);
 }
 
 /**
@@ -3901,12 +3921,15 @@ gtk_widget_size_request (GtkWidget      *widget,
  * since the last time a resize was queued. In general, only container
  * implementations have this information; applications should use
  * gtk_widget_size_request().
+ *
+ *
+ * Deprecated: 3.0: Use gtk_extended_layout_get_desired_size() instead.
  **/
 void
 gtk_widget_get_child_requisition (GtkWidget     *widget,
                                  GtkRequisition *requisition)
 {
-  _gtk_size_group_get_child_requisition (widget, requisition);
+  gtk_extended_layout_get_desired_size (GTK_EXTENDED_LAYOUT (widget), FALSE, requisition, NULL);
 }
 
 static gboolean
@@ -4184,6 +4207,7 @@ gtk_widget_translate_coordinates (GtkWidget  *src_widget,
 {
   GtkWidget *ancestor;
   GdkWindow *window;
+  GList *dest_list = NULL;
 
   g_return_val_if_fail (GTK_IS_WIDGET (src_widget), FALSE);
   g_return_val_if_fail (GTK_IS_WIDGET (dest_widget), FALSE);
@@ -4211,14 +4235,14 @@ gtk_widget_translate_coordinates (GtkWidget  *src_widget,
   window = src_widget->window;
   while (window != ancestor->window)
     {
-      gint dx, dy;
-      
-      gdk_window_get_position (window, &dx, &dy);
-      
-      src_x += dx;
-      src_y += dy;
-      
-      window = gdk_window_get_parent (window);
+      gdouble dx, dy;
+
+      gdk_window_coords_to_parent (window, src_x, src_y, &dx, &dy);
+
+      src_x = dx;
+      src_y = dy;
+
+      window = gdk_window_get_effective_parent (window);
 
       if (!window)             /* Handle GtkHandleBox */
        return FALSE;
@@ -4228,17 +4252,27 @@ gtk_widget_translate_coordinates (GtkWidget  *src_widget,
   window = dest_widget->window;
   while (window != ancestor->window)
     {
-      gint dx, dy;
-      
-      gdk_window_get_position (window, &dx, &dy);
-      
-      src_x -= dx;
-      src_y -= dy;
-      
-      window = gdk_window_get_parent (window);
-      
+      dest_list = g_list_prepend (dest_list, window);
+
+      window = gdk_window_get_effective_parent (window);
+
       if (!window)             /* Handle GtkHandleBox */
-       return FALSE;
+        {
+          g_list_free (dest_list);
+          return FALSE;
+        }
+    }
+
+  while (dest_list)
+    {
+      gdouble dx, dy;
+
+      gdk_window_coords_from_parent (dest_list->data, src_x, src_y, &dx, &dy);
+
+      src_x = dx;
+      src_y = dy;
+
+      dest_list = g_list_remove (dest_list, dest_list->data);
     }
 
   /* Translate from window relative to allocation relative */
@@ -5484,7 +5518,7 @@ gtk_widget_get_can_focus (GtkWidget *widget)
 {
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
-  return (GTK_WIDGET_FLAGS (widget) & GTK_CAN_FOCUS) != 0;
+  return (GTK_OBJECT_FLAGS (widget) & GTK_CAN_FOCUS) != 0;
 }
 
 /**
@@ -5578,7 +5612,7 @@ gtk_widget_get_can_default (GtkWidget *widget)
 {
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
-  return (GTK_WIDGET_FLAGS (widget) & GTK_CAN_DEFAULT) != 0;
+  return (GTK_OBJECT_FLAGS (widget) & GTK_CAN_DEFAULT) != 0;
 }
 
 /**
@@ -5598,7 +5632,17 @@ gtk_widget_has_default (GtkWidget *widget)
 {
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
-  return (GTK_WIDGET_FLAGS (widget) & GTK_HAS_DEFAULT) != 0;
+  return (GTK_OBJECT_FLAGS (widget) & GTK_HAS_DEFAULT) != 0;
+}
+
+void
+_gtk_widget_set_has_default (GtkWidget *widget,
+                             gboolean   has_default)
+{
+  if (has_default)
+    GTK_OBJECT_FLAGS (widget) |= GTK_HAS_DEFAULT;
+  else
+    GTK_OBJECT_FLAGS (widget) &= ~(GTK_HAS_DEFAULT);
 }
 
 /**
@@ -5679,7 +5723,7 @@ gtk_widget_get_receives_default (GtkWidget *widget)
 {
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
-  return (GTK_WIDGET_FLAGS (widget) & GTK_RECEIVES_DEFAULT) != 0;
+  return (GTK_OBJECT_FLAGS (widget) & GTK_RECEIVES_DEFAULT) != 0;
 }
 
 /**
@@ -5700,7 +5744,17 @@ gtk_widget_has_grab (GtkWidget *widget)
 {
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
-  return (GTK_WIDGET_FLAGS (widget) & GTK_HAS_GRAB) != 0;
+  return (GTK_OBJECT_FLAGS (widget) & GTK_HAS_GRAB) != 0;
+}
+
+void
+_gtk_widget_set_has_grab (GtkWidget *widget,
+                          gboolean   has_grab)
+{
+  if (has_grab)
+    GTK_OBJECT_FLAGS (widget) |= GTK_HAS_GRAB;
+  else
+    GTK_OBJECT_FLAGS (widget) &= ~(GTK_HAS_GRAB);
 }
 
 /**
@@ -5929,7 +5983,17 @@ gtk_widget_is_toplevel (GtkWidget *widget)
 {
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
-  return (GTK_WIDGET_FLAGS (widget) & GTK_TOPLEVEL) != 0;
+  return (GTK_OBJECT_FLAGS (widget) & GTK_TOPLEVEL) != 0;
+}
+
+void
+_gtk_widget_set_is_toplevel (GtkWidget *widget,
+                             gboolean   is_toplevel)
+{
+  if (is_toplevel)
+    GTK_OBJECT_FLAGS (widget) |= GTK_TOPLEVEL;
+  else
+    GTK_OBJECT_FLAGS (widget) &= ~(GTK_TOPLEVEL);
 }
 
 /**
@@ -5948,8 +6012,8 @@ gtk_widget_is_drawable (GtkWidget *widget)
 {
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
-  return ((GTK_WIDGET_FLAGS (widget) & GTK_VISIBLE) != 0 &&
-          (GTK_WIDGET_FLAGS (widget) & GTK_MAPPED) != 0);
+  return (gtk_widget_get_visible (widget) &&
+          gtk_widget_get_mapped (widget));
 }
 
 /**
@@ -6100,7 +6164,7 @@ gtk_widget_get_app_paintable (GtkWidget *widget)
 {
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
-  return (GTK_WIDGET_FLAGS (widget) & GTK_APP_PAINTABLE) != 0;
+  return (GTK_OBJECT_FLAGS (widget) & GTK_APP_PAINTABLE) != 0;
 }
 
 /**
@@ -6163,7 +6227,7 @@ gtk_widget_get_double_buffered (GtkWidget *widget)
 {
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
-  return (GTK_WIDGET_FLAGS (widget) & GTK_DOUBLE_BUFFERED) != 0;
+  return (GTK_OBJECT_FLAGS (widget) & GTK_DOUBLE_BUFFERED) != 0;
 }
 
 /**
@@ -6425,7 +6489,7 @@ gtk_widget_has_rc_style (GtkWidget *widget)
 {
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
-  return (GTK_WIDGET_FLAGS (widget) & GTK_RC_STYLE) != 0;
+  return (GTK_OBJECT_FLAGS (widget) & GTK_RC_STYLE) != 0;
 }
 
 /**
@@ -6642,6 +6706,32 @@ gtk_widget_modify_color_component (GtkWidget      *widget,
   gtk_widget_modify_style (widget, rc_style);
 }
 
+/**
+ * gtk_widget_modify_symbolic_color:
+ * @widget: a #GtkWidget
+ * @name: the name of the symbolic color to modify
+ * @color: (allow-none): the color to assign (does not need to be allocated),
+ *         or %NULL to undo the effect of previous calls to
+ *         of gtk_widget_modify_symbolic_color().
+ *
+ * Sets a symbolic color for a widget.
+ * All other style values are left untouched. See also
+ * gtk_widget_modify_style().
+ *
+ * Since: 2.22
+ **/
+void
+gtk_widget_modify_symbolic_color (GtkWidget      *widget,
+                                  const gchar    *name,
+                                  const GdkColor *color)
+{
+  GtkRcStyle *rc_style = gtk_widget_get_modifier_style (widget);
+
+  _gtk_rc_style_set_symbolic_color (rc_style, name, color);
+
+  gtk_widget_modify_style (widget, rc_style);
+}
+
 /**
  * gtk_widget_modify_fg:
  * @widget: a #GtkWidget
@@ -7622,7 +7712,7 @@ gtk_widget_get_root_window (GtkWidget *widget)
  * around the window using keyboard shortcuts. @direction indicates
  * what kind of motion is taking place (up, down, left, right, tab
  * forward, tab backward). gtk_widget_child_focus() emits the
- * #GtkWidget::focus" signal; widgets override the default handler
+ * #GtkWidget::focus signal; widgets override the default handler
  * for this signal in order to implement appropriate focus behavior.
  *
  * The default ::focus handler for a widget should return %TRUE if
@@ -8386,7 +8476,7 @@ gtk_widget_set_composite_name (GtkWidget   *widget,
                               const gchar *name)
 {
   g_return_if_fail (GTK_IS_WIDGET (widget));
-  g_return_if_fail ((GTK_WIDGET_FLAGS (widget) & GTK_COMPOSITE_CHILD) != 0);
+  g_return_if_fail ((GTK_OBJECT_FLAGS (widget) & GTK_COMPOSITE_CHILD) != 0);
   g_return_if_fail (name != NULL);
 
   if (!quark_composite_name)
@@ -8413,7 +8503,7 @@ gtk_widget_get_composite_name (GtkWidget *widget)
 {
   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
 
-  if (((GTK_WIDGET_FLAGS (widget) & GTK_COMPOSITE_CHILD) != 0) && widget->parent)
+  if (((GTK_OBJECT_FLAGS (widget) & GTK_COMPOSITE_CHILD) != 0) && widget->parent)
     return _gtk_container_child_composite_name (GTK_CONTAINER (widget->parent),
                                               widget);
   else
@@ -9031,7 +9121,7 @@ _gtk_widget_synthesize_crossing (GtkWidget      *from,
 
       while (from_ancestor != NULL)
        {
-         from_ancestor = gdk_window_get_parent (from_ancestor);
+         from_ancestor = gdk_window_get_effective_parent (from_ancestor);
           if (from_ancestor == NULL)
             break;
           from_ancestors = g_list_prepend (from_ancestors, from_ancestor);
@@ -9056,7 +9146,7 @@ _gtk_widget_synthesize_crossing (GtkWidget      *from,
 
       while (to_ancestor != NULL)
        {
-         to_ancestor = gdk_window_get_parent (to_ancestor);
+         to_ancestor = gdk_window_get_effective_parent (to_ancestor);
          if (to_ancestor == NULL)
             break;
           to_ancestors = g_list_prepend (to_ancestors, to_ancestor);
@@ -9085,7 +9175,7 @@ _gtk_widget_synthesize_crossing (GtkWidget      *from,
        {
          if (from_ancestor != NULL)
            {
-             from_ancestor = gdk_window_get_parent (from_ancestor);
+             from_ancestor = gdk_window_get_effective_parent (from_ancestor);
              if (from_ancestor == to_window)
                break;
               if (from_ancestor)
@@ -9093,7 +9183,7 @@ _gtk_widget_synthesize_crossing (GtkWidget      *from,
            }
          if (to_ancestor != NULL)
            {
-             to_ancestor = gdk_window_get_parent (to_ancestor);
+             to_ancestor = gdk_window_get_effective_parent (to_ancestor);
              if (to_ancestor == from_window)
                break;
               if (to_ancestor)
@@ -9255,20 +9345,18 @@ _gtk_widget_get_aux_info (GtkWidget *widget,
   aux_info = g_object_get_qdata (G_OBJECT (widget), quark_aux_info);
   if (!aux_info && create)
     {
-      aux_info = g_slice_new (GtkWidgetAuxInfo);
+      aux_info = g_slice_new0 (GtkWidgetAuxInfo);
 
       aux_info->width = -1;
       aux_info->height = -1;
-      aux_info->x = 0;
-      aux_info->y = 0;
-      aux_info->x_set = FALSE;
-      aux_info->y_set = FALSE;
+
       g_object_set_qdata (G_OBJECT (widget), quark_aux_info, aux_info);
     }
   
   return aux_info;
 }
 
+
 /*****************************************
  * gtk_widget_aux_info_destroy:
  *
@@ -10701,7 +10789,67 @@ gtk_widget_buildable_custom_finished (GtkBuildable *buildable,
     }
 }
 
+/*
+ * GtkExtendedLayout implementation
+ */
+static void
+gtk_widget_real_get_desired_width (GtkExtendedLayout *layout,
+                                  gint              *minimum_size,
+                                  gint              *natural_size)
+{
+  /* Set the initial values so that unimplemented classes will fall back
+   * on the "size-request" collected values (see gtksizegroup.c:do_size_request()).
+   */
+  if (minimum_size)
+    *minimum_size = GTK_WIDGET (layout)->requisition.width;
+
+  if (natural_size)
+    *natural_size = GTK_WIDGET (layout)->requisition.width;
+}
+
+static void
+gtk_widget_real_get_desired_height (GtkExtendedLayout *layout,
+                                   gint              *minimum_size,
+                                   gint              *natural_size)
+{
+  /* Set the initial values so that unimplemented classes will fall back
+   * on the "size-request" collected values (see gtksizegroup.c:do_size_request()).
+   */
+  if (minimum_size)
+    *minimum_size = GTK_WIDGET (layout)->requisition.height;
+
+  if (natural_size)
+    *natural_size = GTK_WIDGET (layout)->requisition.height;
+}
 
+static void
+gtk_widget_real_get_height_for_width (GtkExtendedLayout *layout,
+                                      gint       width,
+                                      gint      *minimum_height,
+                                      gint      *natural_height)
+{
+  gtk_extended_layout_get_desired_height (layout, minimum_height, natural_height);
+}
+
+static void
+gtk_widget_real_get_width_for_height (GtkExtendedLayout *layout,
+                                      gint       height,
+                                      gint      *minimum_width,
+                                      gint      *natural_width)
+{ 
+  gtk_extended_layout_get_desired_width (layout, minimum_width, natural_width);
+}
+
+static void
+gtk_widget_extended_layout_init (GtkExtendedLayoutIface *iface)
+{
+  iface->get_desired_width    = gtk_widget_real_get_desired_width;
+  iface->get_desired_height   = gtk_widget_real_get_desired_height;
+  iface->get_width_for_height = gtk_widget_real_get_width_for_height;
+  iface->get_height_for_width = gtk_widget_real_get_height_for_width;  
+}
 /**
  * gtk_widget_get_clipboard:
  * @widget: a #GtkWidget
@@ -11273,5 +11421,71 @@ gtk_widget_get_window (GtkWidget *widget)
   return widget->window;
 }
 
+static void
+_gtk_widget_set_has_focus (GtkWidget *widget,
+                           gboolean   has_focus)
+{
+  if (has_focus)
+    GTK_OBJECT_FLAGS (widget) |= GTK_HAS_FOCUS;
+  else
+    GTK_OBJECT_FLAGS (widget) &= ~(GTK_HAS_FOCUS);
+}
+
+/**
+ * gtk_widget_send_focus_change:
+ * @widget: a #GtkWidget
+ * @event: a #GdkEvent of type GDK_FOCUS_CHANGE
+ *
+ * Sends the focus change @event to @widget
+ *
+ * This function is not meant to be used by applications. The only time it
+ * should be used is when it is necessary for a #GtkWidget to assign focus
+ * to a widget that is semantically owned by the first widget even though
+ * it's not a direct child - for instance, a search entry in a floating
+ * window similar to the quick search in #GtkTreeView.
+ *
+ * An example of its usage is:
+ *
+ * |[
+ *   GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
+ *
+ *   fevent->focus_change.type = GDK_FOCUS_CHANGE;
+ *   fevent->focus_change.in = TRUE;
+ *   fevent->focus_change.window = gtk_widget_get_window (widget);
+ *   if (fevent->focus_change.window != NULL)
+ *     g_object_ref (fevent->focus_change.window);
+ *
+ *   gtk_widget_send_focus_change (widget, fevent);
+ *
+ *   gdk_event_free (event);
+ * ]|
+ *
+ * Return value: the return value from the event signal emission: %TRUE
+ *   if the event was handled, and %FALSE otherwise
+ *
+ * Since: 2.20
+ */
+gboolean
+gtk_widget_send_focus_change (GtkWidget *widget,
+                              GdkEvent  *event)
+{
+  gboolean res;
+
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+  g_return_val_if_fail (event != NULL && event->type == GDK_FOCUS_CHANGE, FALSE);
+
+  g_object_ref (widget);
+
+  _gtk_widget_set_has_focus (widget, event->focus_change.in);
+
+  res = gtk_widget_event (widget, event);
+
+  g_object_notify (G_OBJECT (widget), "has-focus");
+
+  g_object_unref (widget);
+
+  return res;
+}
+
 #define __GTK_WIDGET_C__
 #include "gtkaliasdef.c"