[gtk+/drop-gail: 1/24] First cut at moving GailWidget -> GtkWidgetAccessible



commit 08f329c6bc69a67c71e98da941ab3174145c8399
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Feb 21 01:00:07 2011 -0500

    First cut at moving GailWidget -> GtkWidgetAccessible

 gtk/gtkwidget.c |  822 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 806 insertions(+), 16 deletions(-)
---
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index cece4de..b38f072 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -11935,23 +11935,18 @@ gtk_widget_real_get_accessible (GtkWidget *widget)
 {
   AtkObject* accessible;
 
-  accessible = g_object_get_qdata (G_OBJECT (widget),
-                                   quark_accessible_object);
+  accessible = g_object_get_qdata (G_OBJECT (widget), quark_accessible_object);
   if (!accessible)
-  {
-    AtkObjectFactory *factory;
-    AtkRegistry *default_registry;
-
-    default_registry = atk_get_default_registry ();
-    factory = atk_registry_get_factory (default_registry,
-                                        G_TYPE_FROM_INSTANCE (widget));
-    accessible =
-      atk_object_factory_create_accessible (factory,
-					    G_OBJECT (widget));
-    g_object_set_qdata (G_OBJECT (widget),
-                        quark_accessible_object,
-                        accessible);
-  }
+    {
+      AtkObjectFactory *factory;
+      AtkRegistry *default_registry;
+
+      default_registry = atk_get_default_registry ();
+      factory = atk_registry_get_factory (default_registry, G_TYPE_FROM_INSTANCE (widget));
+      accessible = atk_object_factory_create_accessible (factory, G_OBJECT (widget));
+      g_object_set_qdata (G_OBJECT (widget), quark_accessible_object, accessible);
+    }
+
   return accessible;
 }
 
@@ -14365,3 +14360,798 @@ gtk_widget_get_style_context (GtkWidget *widget)
 
   return widget->priv->context;
 }
+
+/* --- Accessibility --- */
+
+#define GTK_TYPE_WIDGET_ACCESSIBLE (gtk_widget_accessible_get_type ())
+#define GTK_WIDGET_ACCESSIBLE(obj)(G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WIDGET_ACCESSIBLE, GtkWidgetAccessible))
+#define GTK_WIDGET_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WIDGET_ACCESSIBLE, GtkWidgetAccessibleClass))
+
+typedef struct _GtkWidgetAccessible GtkWidgetAccessible;
+typedef struct _GtkWidgetAccessibleClass GtkWidgetAccessibleClass;
+
+struct _GtkWidgetAccessible
+{
+  GtkAccessible parent;
+};
+
+struct _GtkWidgetAccessibleClass
+{
+  GtkAccessibleClass parent_class;
+
+  /* FIXME: drop these */
+  void     (*notify_gtk) (GObject       *object,
+                          GParamSpec    *pspec);
+  gboolean (*focus_gtk)  (GtkWidget     *widget,
+                          GdkEventFocus *event);
+};
+
+static void atk_component_interface_init (AtkComponentIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtkWidgetAccessible, gtk_widget_accessible, GTK_TYPE_ACCESSIBLE,
+                         G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, atk_component_interface_init))
+
+static void
+gtk_widget_accessible_init (GtkWidgetAccessible *accessible)
+{
+}
+
+static gboolean
+gtk_widget_accessible_focus_cb (GtkWidget     *widget,
+                                GdkEventFocus *event)
+{
+  GtkWidgetAccessible *accessible;
+
+  accessible = GTK_WIDGET_ACCESSIBLE (gtk_widget_get_accessible (widget));
+
+  return GTK_WIDGET_ACCESSIBLE_GET_CLASS (accessible)->focus_gtk (widget, event);
+}
+
+static gboolean
+gtk_widget_accessible_focus_gtk (GtkWidget     *widget,
+                                 GdkEventFocus *event)
+{
+  AtkObject* accessible;
+  gboolean return_val;
+  return_val = FALSE;
+
+  accessible = gtk_widget_get_accessible (widget);
+  g_signal_emit_by_name (accessible, "focus_event", event->in, &return_val);
+  return FALSE;
+}
+
+static void
+gtk_widget_accessible_notify_cb (GObject    *object,
+                                 GParamSpec *pspec)
+{
+  GtkWidget *widget;
+  GtkWidgetAccessible *accessible;
+
+  widget = GTK_WIDGET (object);
+  accessible = GTK_WIDGET_ACCESSIBLE (gtk_widget_get_accessible (widget));
+
+  GTK_WIDGET_ACCESSIBLE_GET_CLASS (accessible)->notify_gtk (object, pspec);
+}
+
+static void
+gtk_widget_accessible_notify_gtk (GObject    *object,
+                                  GParamSpec *pspec)
+{
+  GtkWidget* widget = GTK_WIDGET (object);
+  AtkObject* atk_obj = gtk_widget_get_accessible (widget);
+  AtkState state;
+  gboolean value;
+
+  if (strcmp (pspec->name, "visible") == 0)
+    {
+      state = ATK_STATE_VISIBLE;
+      value = gtk_widget_get_visible (widget);
+    }
+  else if (strcmp (pspec->name, "sensitive") == 0)
+    {
+      state = ATK_STATE_SENSITIVE;
+      value = gtk_widget_get_sensitive (widget);
+    }
+  else if (strcmp (pspec->name, "orientation") == 0)
+    {
+      GtkOrientable *orientable;
+
+      orientable = GTK_ORIENTABLE (widget);
+
+      state = ATK_STATE_HORIZONTAL;
+      value = (gtk_orientable_get_orientation (orientable) == GTK_ORIENTATION_HORIZONTAL);
+    }
+  else
+    return;
+
+  atk_object_notify_state_change (atk_obj, state, value);
+  if (state == ATK_STATE_SENSITIVE)
+    atk_object_notify_state_change (atk_obj, ATK_STATE_ENABLED, value);
+
+  if (state == ATK_STATE_HORIZONTAL)
+    atk_object_notify_state_change (atk_obj, ATK_STATE_VERTICAL, !value);
+}
+
+static void
+gtk_widget_accessible_size_allocate_cb (GtkWidget     *widget,
+                                        GtkAllocation *allocation)
+{
+  AtkObject* accessible;
+  AtkRectangle rect;
+
+  accessible = gtk_widget_get_accessible (widget);
+
+  rect.x = allocation->x;
+  rect.y = allocation->y;
+  rect.width = allocation->width;
+  rect.height = allocation->height;
+
+  g_signal_emit_by_name (accessible, "bounds_changed", &rect);
+}
+
+static void
+gtk_widget_accessible_focus_event (AtkObject *obj,
+                                   gboolean   focus_in)
+{
+  AtkObject *focus_obj;
+
+  /* FIXME: focus tracking in gail is totally insane */
+  focus_obj = g_object_get_data (G_OBJECT (obj), "gail-focus-object");
+  if (focus_obj == NULL)
+    focus_obj = obj;
+  atk_object_notify_state_change (focus_obj, ATK_STATE_FOCUSED, focus_in);
+}
+
+static void
+gtk_widget_accessible_map_cb (GtkWidget *widget)
+{
+  AtkObject* accessible;
+
+  accessible = gtk_widget_get_accessible (widget);
+  atk_object_notify_state_change (accessible, ATK_STATE_SHOWING,
+                                  gtk_widget_get_mapped (widget));
+}
+
+static void
+gtk_widget_accessible_initialize (AtkObject *obj,
+                                  gpointer   data)
+{
+  GtkAccessible *accessible;
+  GtkWidget *widget;
+
+  widget = GTK_WIDGET (data);
+
+  accessible = GTK_ACCESSIBLE (obj);
+  atk_object_set_role (ATK_OBJECT (accessible), ATK_ROLE_UNKNOWN);
+
+  gtk_accessible_set_widget (accessible, widget);
+  gtk_accessible_connect_widget_destroyed (accessible);
+
+  /* FIXME: move all this into the class handlers
+   * and get rid of the duplicated signals on GtkWidgetAccessible
+   */
+  g_signal_connect_after (widget, "focus-in-event",
+                          G_CALLBACK (gtk_widget_accessible_focus_cb), NULL);
+  g_signal_connect_after (widget, "focus-out-event",
+                          G_CALLBACK (gtk_widget_accessible_focus_cb), NULL);
+  g_signal_connect (widget, "notify",
+                    G_CALLBACK (gtk_widget_accessible_notify_cb), NULL);
+  g_signal_connect (widget, "size_allocate",
+                    G_CALLBACK (gtk_widget_accessible_size_allocate_cb), NULL);
+
+  atk_component_add_focus_handler (ATK_COMPONENT (accessible),
+                                   gtk_widget_accessible_focus_event);
+
+  g_signal_connect (widget, "map",
+                    G_CALLBACK (gtk_widget_accessible_map_cb), NULL);
+  g_signal_connect (widget, "unmap",
+                    G_CALLBACK (gtk_widget_accessible_map_cb), NULL);
+}
+
+static G_CONST_RETURN gchar*
+gtk_widget_accessible_get_description (AtkObject *accessible)
+{
+  GtkWidget *widget;
+
+  if (accessible->description)
+    return accessible->description;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
+  if (widget == NULL)
+    return NULL;
+
+  /* FIXME: memory leak */
+  return gtk_widget_get_tooltip_text (widget);
+}
+
+static AtkObject *
+gtk_widget_accessible_get_parent (AtkObject *accessible)
+{
+  GtkWidget *widget, *parent_widget;
+
+  if (accessible->accessible_parent)
+    return accessible->accessible_parent;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
+  if (widget == NULL)
+    return NULL;
+
+  parent_widget = gtk_widget_get_parent (widget);
+  if (parent_widget == NULL)
+    return NULL;
+
+  /* FIXME: turn this into a get_parent_for_child vfunc */
+  if (GTK_IS_NOTEBOOK (parent_widget))
+    {
+      gint page_num;
+      GtkWidget *child;
+      GtkNotebook *notebook;
+      AtkObject *parent;
+
+      page_num = 0;
+      notebook = GTK_NOTEBOOK (parent_widget);
+      while (TRUE)
+        {
+          child = gtk_notebook_get_nth_page (notebook, page_num);
+          if (!child)
+            break;
+          if (child == widget)
+            {
+              parent = (AtkObject *)gtk_widget_get_accessible (parent_widget);
+              parent = atk_object_ref_accessible_child (parent, page_num);
+              g_object_unref (parent);
+              return parent;
+            }
+          page_num++;
+        }
+    }
+
+  return gtk_widget_get_accessible (parent_widget);
+}
+
+static gint
+gtk_widget_accessible_get_index_in_parent (AtkObject *accessible)
+{
+  GtkWidget *widget;
+  AtkObject *parent;
+  GtkWidget *parent_widget;
+  gint index;
+  GList *children;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
+
+  if (widget == NULL)
+    return -1;
+
+  parent = accessible->accessible_parent;
+  if (parent)
+    {
+#if 0
+      /* FIXME: turn this into a  vfunc on the parent */
+      if (GAIL_IS_NOTEBOOK_PAGE (parent))
+        return 0;
+      else
+        {
+          gint n_children, i;
+          gboolean found = FALSE;
+
+          n_children = atk_object_get_n_accessible_children (parent);
+          for (i = 0; i < n_children; i++)
+            {
+              AtkObject *child;
+
+              child = atk_object_ref_accessible_child (parent, i);
+              if (child == accessible)
+                found = TRUE;
+
+              g_object_unref (child);
+              if (found)
+                return i;
+            }
+        }
+#endif
+    }
+
+  parent_widget = gtk_widget_get_parent (widget);
+  if (parent_widget == NULL)
+    return -1;
+
+  children = gtk_container_get_children (GTK_CONTAINER (parent_widget));
+
+  index = g_list_index (children, widget);
+  g_list_free (children);
+
+  return index;
+}
+
+static void
+gtk_widget_accessible_widget_destroyed (GtkWidget     *widget,
+                                        GtkAccessible *accessible)
+{
+  atk_object_notify_state_change (ATK_OBJECT (accessible), ATK_STATE_DEFUNCT,
+                                  TRUE);
+}
+
+/* FIXME: Should just have a GtkAccessible::widget property */
+static void
+gtk_widget_accessible_connect_widget_destroyed (GtkAccessible *accessible)
+{
+  GtkWidget *widget;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
+  if (widget)
+    g_signal_connect_after (widget, "destroy",
+                            G_CALLBACK (gtk_widget_accessible_widget_destroyed),
+                            accessible);
+}
+
+static GtkWidget*
+find_label (GtkWidget *widget)
+{
+  GList *labels;
+  GtkWidget *label;
+
+  labels = gtk_widget_list_mnemonic_labels (widget);
+  label = NULL;
+  if (labels)
+    {
+      if (labels->next)
+        g_warning ("Widget (%s) has more than one label", G_OBJECT_TYPE_NAME (widget));
+      label = labels->data;
+    }
+  g_list_free (labels);
+
+  /* Ignore a label within a button; bug #136602 */
+  if (label &&
+      GTK_IS_BUTTON (widget) &&
+      gtk_widget_is_ancestor (label, widget))
+    {
+      label = NULL;
+    }
+
+  return label;
+}
+
+static AtkRelationSet*
+gtk_widget_accessible_ref_relation_set (AtkObject *obj)
+{
+  GtkWidget *widget;
+  AtkRelationSet *relation_set;
+  GtkWidget *label;
+  AtkObject *array[1];
+  AtkRelation* relation;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
+  if (widget == NULL)
+    return NULL;
+
+  relation_set = ATK_OBJECT_CLASS (gtk_widget_accessible_parent_class)->ref_relation_set (obj);
+
+  if (!atk_relation_set_contains (relation_set, ATK_RELATION_LABELLED_BY))
+    {
+      label = find_label (widget);
+
+      if (label)
+        {
+          array[0] = gtk_widget_get_accessible (label);
+
+          relation = atk_relation_new (array, 1, ATK_RELATION_LABELLED_BY);
+          atk_relation_set_add (relation_set, relation);
+          g_object_unref (relation);
+        }
+    }
+
+  return relation_set;
+}
+
+/*
+ * This function checks whether the widget has an antecedent which is
+ * a GtkViewport and, if so, whether any part of the widget intersects
+ * the visible rectangle of the GtkViewport.
+ *
+ * FIXME: this does not work for child widgets in scrollable containers
+ * like gtktextview or gtkiconview. Needs to be a container vfunc, probably
+ */
+static gboolean
+gtk_widget_on_screen (GtkWidget *widget)
+{
+  GtkAllocation allocation;
+  GtkWidget *viewport;
+  gboolean return_value;
+
+  gtk_widget_get_allocation (widget, &allocation);
+
+  viewport = gtk_widget_get_ancestor (widget, GTK_TYPE_VIEWPORT);
+  if (viewport)
+    {
+      GtkAllocation viewport_allocation;
+      GtkAdjustment *adjustment;
+      GdkRectangle visible_rect;
+
+      gtk_widget_get_allocation (viewport, &viewport_allocation);
+      adjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (viewport));
+      visible_rect.y = gtk_adjustment_get_value (adjustment);
+      adjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (viewport));
+      visible_rect.x = gtk_adjustment_get_value (adjustment);
+      visible_rect.width = viewport_allocation.width;
+      visible_rect.height = viewport_allocation.height;
+
+      if (((allocation.x + allocation.width) < visible_rect.x) ||
+         ((allocation.y + allocation.height) < visible_rect.y) ||
+         (allocation.x > (visible_rect.x + visible_rect.width)) ||
+         (allocation.y > (visible_rect.y + visible_rect.height)))
+        return_value = FALSE;
+      else
+        return_value = TRUE;
+    }
+  else
+    {
+      /*
+       * Check whether the widget has been placed of the screen.
+       * The widget may be MAPPED as when toolbar items do not fit
+       * on the toolbar.
+       */
+      if (allocation.x + allocation.width <= 0 &&
+          allocation.y + allocation.height <= 0)
+        return_value = FALSE;
+      else
+        return_value = TRUE;
+    }
+
+  return return_value;
+}
+
+static AtkStateSet*
+gtk_widget_accessible_ref_state_set (AtkObject *accessible)
+{
+  GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
+  AtkStateSet *state_set;
+
+  state_set = ATK_OBJECT_CLASS (gtk_widget_accessible_parent_class)->ref_state_set (accessible);
+
+  if (widget == NULL)
+    {
+      atk_state_set_add_state (state_set, ATK_STATE_DEFUNCT);
+    }
+  else
+    {
+      if (gtk_widget_is_sensitive (widget))
+        {
+          atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE);
+          atk_state_set_add_state (state_set, ATK_STATE_ENABLED);
+        }
+
+      if (gtk_widget_get_can_focus (widget))
+        {
+          atk_state_set_add_state (state_set, ATK_STATE_FOCUSABLE);
+        }
+
+      if (gtk_widget_get_visible (widget))
+        {
+          atk_state_set_add_state (state_set, ATK_STATE_VISIBLE);
+          if (gtk_widget_get_mapped (widget) &&
+              gtk_widget_on_screen (widget))
+            {
+              atk_state_set_add_state (state_set, ATK_STATE_SHOWING);
+            }
+        }
+
+      if (gtk_widget_has_focus (widget))
+        {
+          AtkObject *focus_obj;
+
+          focus_obj = g_object_get_data (G_OBJECT (accessible), "gail-focus-object");
+          if (focus_obj == NULL)
+            atk_state_set_add_state (state_set, ATK_STATE_FOCUSED);
+        }
+
+      if (gtk_widget_has_default (widget))
+        {
+          atk_state_set_add_state (state_set, ATK_STATE_DEFAULT);
+        }
+
+      if (GTK_IS_ORIENTABLE(widget))
+        switch (gtk_orientable_get_orientation (GTK_ORIENTABLE (widget)))
+          {
+          case GTK_ORIENTATION_HORIZONTAL:
+            atk_state_set_add_state (state_set, ATK_STATE_HORIZONTAL);
+            break;
+
+          case GTK_ORIENTATION_VERTICAL:
+            atk_state_set_add_state (state_set, ATK_STATE_VERTICAL);
+            break;
+          }
+    }
+
+  return state_set;
+}
+
+static AtkAttributeSet *
+gtk_widget_accessible_get_attributes (AtkObject *obj)
+{
+  AtkAttributeSet *attributes;
+  AtkAttribute *attribute;
+
+  attribute = g_new (AtkAttribute, 1);
+
+  attribute->name = g_strdup ("toolkit");
+  attribute->value = g_strdup( "gtk");
+
+  attributes = g_slist_append (NULL, attribute);
+
+  return attributes;
+}
+
+static void
+gtk_widget_accessible_class_init (GtkWidgetAccessibleClass *klass)
+{
+  AtkObjectClass *atkobject_class = ATK_OBJECT_CLASS (klass);
+  GtkAccessibleClass *accessible_class = GTK_ACCESSIBLE_CLASS (klass);
+
+  atkobject_class->initialize = gtk_widget_accessible_initialize;
+  atkobject_class->get_description = gtk_widget_accessible_get_description;
+  atkobject_class->get_parent = gtk_widget_accessible_get_parent;
+  atkobject_class->get_index_in_parent = gtk_widget_accessible_get_index_in_parent;
+  atkobject_class->ref_relation_set = gtk_widget_accessible_ref_relation_set;
+  atkobject_class->ref_state_set = gtk_widget_accessible_ref_state_set;
+  atkobject_class->get_attributes = gtk_widget_accessible_get_attributes;
+
+  accessible_class->connect_widget_destroyed = gtk_widget_accessible_connect_widget_destroyed;
+
+  klass->focus_gtk = gtk_widget_accessible_focus_gtk;
+  klass->notify_gtk = gtk_widget_accessible_notify_gtk;
+}
+
+static guint
+gtk_widget_accessible_add_focus_handler (AtkComponent    *component,
+                                         AtkFocusHandler  handler)
+{
+  guint signal_id;
+
+  signal_id = g_signal_lookup ("focus-event", ATK_TYPE_OBJECT);
+
+  if (g_signal_handler_find (component,
+                             G_SIGNAL_MATCH_ID|G_SIGNAL_MATCH_FUNC,
+                             signal_id,
+                             0, NULL, (gpointer) handler, NULL))
+    return 0;
+
+  return g_signal_connect_closure_by_id (component,
+                                         signal_id, 0,
+                                         g_cclosure_new (G_CALLBACK (handler), NULL,
+                                                         (GClosureNotify) NULL),
+                                         FALSE);
+}
+
+static void
+gtk_widget_accessible_remove_focus_handler (AtkComponent *component,
+                                            guint         handler_id)
+{
+  g_signal_handler_disconnect (component, handler_id);
+}
+
+static void
+gtk_widget_accessible_get_extents (AtkComponent *component,
+                                   gint         *x,
+                                   gint         *y,
+                                   gint         *width,
+                                   gint         *height,
+                                   AtkCoordType  coord_type)
+{
+  GtkAllocation allocation;
+  GdkWindow *window;
+  gint x_window, y_window;
+  gint x_toplevel, y_toplevel;
+  GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
+
+  if (widget == NULL)
+    return;
+
+  gtk_widget_get_allocation (widget, &allocation);
+  *width = allocation.width;
+  *height = allocation.height;
+
+  if (!gtk_widget_on_screen (widget) || !gtk_widget_is_drawable (widget))
+    {
+      *x = G_MININT;
+      *y = G_MININT;
+
+      return;
+    }
+
+  if (gtk_widget_get_parent (widget))
+    {
+      *x = allocation.x;
+      *y = allocation.y;
+      window = gtk_widget_get_parent_window (widget);
+    }
+  else
+    {
+      *x = 0;
+      *y = 0;
+      window = gtk_widget_get_window (widget);
+    }
+
+  gdk_window_get_origin (window, &x_window, &y_window);
+  *x += x_window;
+  *y += y_window;
+
+  if (coord_type == ATK_XY_WINDOW)
+    {
+      window = gdk_window_get_toplevel (gtk_widget_get_window (widget));
+      gdk_window_get_origin (window, &x_toplevel, &y_toplevel);
+
+      *x -= x_toplevel;
+      *y -= y_toplevel;
+    }
+}
+
+/* FIXME: move to GtkWindow */
+static gboolean
+gtk_widget_accessible_set_extents (AtkComponent *component,
+                                   gint          x,
+                                   gint          y,
+                                   gint          width,
+                                   gint          height,
+                                   AtkCoordType  coord_type)
+{
+  GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
+
+  if (widget == NULL)
+    return FALSE;
+
+  if (!gtk_widget_is_toplevel (widget))
+    return FALSE;
+
+  if (coord_type == ATK_XY_WINDOW)
+    {
+      gint x_current, y_current;
+      GdkWindow *window;
+
+      window = gtk_widget_get_window (widget);
+      gdk_window_get_origin (window, &x_current, &y_current);
+      x_current += x;
+      y_current += y;
+      if (x_current < 0 || y_current < 0)
+        return FALSE;
+      else
+        {
+          gtk_window_move (GTK_WINDOW (widget), x_current, y_current);
+          gtk_widget_set_size_request (widget, width, height);
+          return TRUE;
+        }
+    }
+  else if (coord_type == ATK_XY_SCREEN)
+    {
+      gtk_window_move (GTK_WINDOW (widget), x, y);
+      gtk_widget_set_size_request (widget, width, height);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+/* FIXME: move to GtkWindow */
+static gboolean
+gtk_widget_accessible_set_position (AtkComponent *component,
+                                    gint          x,
+                                    gint          y,
+                                    AtkCoordType  coord_type)
+{
+  GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
+
+  if (widget == NULL)
+    return FALSE;
+
+  if (!gtk_widget_is_toplevel (widget))
+    return FALSE;
+
+  if (coord_type == ATK_XY_WINDOW)
+    {
+      gint x_current, y_current;
+      GdkWindow *window;
+
+      window = gtk_widget_get_window (widget);
+      gdk_window_get_origin (window, &x_current, &y_current);
+      x_current += x;
+      y_current += y;
+      if (x_current < 0 || y_current < 0)
+        return FALSE;
+      else
+        {
+          gtk_window_move (GTK_WINDOW (widget), x_current, y_current);
+          return TRUE;
+        }
+    }
+  else if (coord_type == ATK_XY_SCREEN)
+    {
+      gtk_window_move (GTK_WINDOW (widget), x, y);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+gtk_widget_accessible_get_size (AtkComponent *component,
+                                gint         *width,
+                                gint         *height)
+{
+  GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
+
+  if (widget == NULL)
+    return;
+
+  *width = gtk_widget_get_allocated_width (widget);
+  *height = gtk_widget_get_allocated_height (widget);
+}
+
+/* FIXME: move to GtkWindow */
+static gboolean
+gtk_widget_accessible_set_size (AtkComponent *component,
+                                gint          width,
+                                gint          height)
+{
+  GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
+
+  if (widget == NULL)
+    return FALSE;
+
+  if (!gtk_widget_is_toplevel (widget))
+    return FALSE;
+
+  gtk_widget_set_size_request (widget, width, height);
+
+  return TRUE;
+}
+
+static AtkLayer
+gtk_widget_accessible_get_layer (AtkComponent *component)
+{
+  return ATK_LAYER_WIDGET;
+}
+
+static gboolean
+gtk_widget_accessible_grab_focus (AtkComponent *component)
+{
+  GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
+  GtkWidget *toplevel;
+
+  if (widget == NULL)
+    return FALSE;
+
+  if (!gtk_widget_get_can_focus (widget))
+    return FALSE;
+
+  gtk_widget_grab_focus (widget);
+  toplevel = gtk_widget_get_toplevel (widget);
+  if (gtk_widget_is_toplevel (toplevel))
+    {
+      guint32 timestamp;
+
+#ifdef GDK_WINDOWING_X11
+      if (GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)))
+        timestamp = gdk_x11_get_server_time (gtk_widget_get_window (widget));
+      else
+#endif
+        timestamp = GDK_CURRENT_TIME;
+
+      gtk_window_present_with_time (GTK_WINDOW (toplevel), timestamp);
+    }
+
+  return TRUE;
+}
+
+static void
+atk_component_interface_init (AtkComponentIface *iface)
+{
+  iface->add_focus_handler = gtk_widget_accessible_add_focus_handler;
+  iface->remove_focus_handler = gtk_widget_accessible_remove_focus_handler;
+  iface->get_extents = gtk_widget_accessible_get_extents;
+  iface->set_extents = gtk_widget_accessible_set_extents;
+  iface->set_position = gtk_widget_accessible_set_position;
+  iface->get_size = gtk_widget_accessible_get_size;
+  iface->set_size = gtk_widget_accessible_set_size;
+  iface->get_layer = gtk_widget_accessible_get_layer;
+  iface->grab_focus = gtk_widget_accessible_grab_focus;
+}



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