bug 1305402 - implement the AtkTablecell interface r=davidb
☠☠ backed out by 34bc558363a1 ☠ ☠
authorTrevor Saunders <tbsaunde@tbsaunde.org>
Wed, 28 Sep 2016 11:08:45 -0400
changeset 424994 3152577aab9bbac3410a57447003291371351c7b
parent 424993 28272f824ad0c62b5af2bafdefeb8d66631897b1
child 424995 20754fd4499aedb03b7dfeeb5499c18bfbb1c497
push id32314
push userbmo:hiikezoe@mozilla-japan.org
push dateFri, 14 Oct 2016 00:31:54 +0000
reviewersdavidb
bugs1305402
milestone52.0a1
bug 1305402 - implement the AtkTablecell interface r=davidb This is a pretty straight forward wrapper around the internal table cell interface. However we need to be careful to only expose this interface if we are dealing with a version of ATK new enough to understand it.
accessible/atk/AccessibleWrap.cpp
accessible/atk/InterfaceInitFuncs.h
accessible/atk/moz.build
accessible/atk/nsMaiInterfaceTableCell.cpp
--- a/accessible/atk/AccessibleWrap.cpp
+++ b/accessible/atk/AccessibleWrap.cpp
@@ -61,17 +61,18 @@ enum MaiInterfaceType {
     MAI_INTERFACE_VALUE,
     MAI_INTERFACE_EDITABLE_TEXT,
     MAI_INTERFACE_HYPERTEXT,
     MAI_INTERFACE_HYPERLINK_IMPL,
     MAI_INTERFACE_SELECTION,
     MAI_INTERFACE_TABLE,
     MAI_INTERFACE_TEXT,
     MAI_INTERFACE_DOCUMENT, 
-    MAI_INTERFACE_IMAGE /* 10 */
+    MAI_INTERFACE_IMAGE, /* 10 */
+    MAI_INTERFACE_TABLE_CELL
 };
 
 static GType GetAtkTypeForMai(MaiInterfaceType type)
 {
   switch (type) {
     case MAI_INTERFACE_COMPONENT:
       return ATK_TYPE_COMPONENT;
     case MAI_INTERFACE_ACTION:
@@ -89,22 +90,27 @@ static GType GetAtkTypeForMai(MaiInterfa
     case MAI_INTERFACE_TABLE:
       return ATK_TYPE_TABLE;
     case MAI_INTERFACE_TEXT:
       return ATK_TYPE_TEXT;
     case MAI_INTERFACE_DOCUMENT:
       return ATK_TYPE_DOCUMENT;
     case MAI_INTERFACE_IMAGE:
       return ATK_TYPE_IMAGE;
+    case MAI_INTERFACE_TABLE_CELL:
+      MOZ_ASSERT(false);
   }
   return G_TYPE_INVALID;
 }
 
 #define NON_USER_EVENT ":system"
     
+// The atk interfaces we can expose without checking what version of ATK we are
+// dealing with.  At the moment AtkTableCell is the only interface we can't
+// always expose.
 static const GInterfaceInfo atk_if_infos[] = {
     {(GInterfaceInitFunc)componentInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr}, 
     {(GInterfaceInitFunc)actionInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)valueInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)editableTextInterfaceInitCB,
@@ -420,16 +426,25 @@ GetMaiAtkType(uint16_t interfacesBits)
     for (uint32_t index = 0; index < ArrayLength(atk_if_infos); index++) {
       if (interfacesBits & (1 << index)) {
         g_type_add_interface_static(type,
                                     GetAtkTypeForMai((MaiInterfaceType)index),
                                     &atk_if_infos[index]);
       }
     }
 
+    // Special case AtkTableCell so we can check what version of Atk we are
+    // dealing with.
+    if (IsAtkVersionAtLeast(2, 12) && (interfacesBits & (1 << MAI_INTERFACE_TABLE_CELL))) {
+      const GInterfaceInfo cellInfo = {
+        (GInterfaceInitFunc)tableCellInterfaceInitCB,
+        (GInterfaceFinalizeFunc)nullptr, nullptr};
+      g_type_add_interface_static(type, ATK_TYPE_TABLE_CELL, &cellInfo);
+    }
+
     return type;
 }
 
 static const char*
 GetUniqueMaiAtkTypeName(uint16_t interfacesBits)
 {
 #define MAI_ATK_TYPE_NAME_LEN (30)     /* 10+sizeof(uint16_t)*8/4+1 < 30 */
 
--- a/accessible/atk/InterfaceInitFuncs.h
+++ b/accessible/atk/InterfaceInitFuncs.h
@@ -22,16 +22,17 @@ void actionInterfaceInitCB(AtkActionIfac
 void componentInterfaceInitCB(AtkComponentIface* aIface);
 void documentInterfaceInitCB(AtkDocumentIface *aIface);
 void editableTextInterfaceInitCB(AtkEditableTextIface* aIface);
 void hyperlinkImplInterfaceInitCB(AtkHyperlinkImplIface *aIface);
 void hypertextInterfaceInitCB(AtkHypertextIface* aIface);
 void imageInterfaceInitCB(AtkImageIface* aIface);
 void selectionInterfaceInitCB(AtkSelectionIface* aIface);
 void tableInterfaceInitCB(AtkTableIface *aIface);
+void tableCellInterfaceInitCB(AtkTableCellIface *aIface);
 void textInterfaceInitCB(AtkTextIface* aIface);
 void valueInterfaceInitCB(AtkValueIface *aIface);
 }
 
 /**
  * XXX these should live in a file of utils for atk.
  */
 AtkObject* refAccessibleAtPointHelper(AtkObject* aAtkObj,
--- a/accessible/atk/moz.build
+++ b/accessible/atk/moz.build
@@ -19,16 +19,17 @@ SOURCES += [
     'nsMaiInterfaceComponent.cpp',
     'nsMaiInterfaceDocument.cpp',
     'nsMaiInterfaceEditableText.cpp',
     'nsMaiInterfaceHyperlinkImpl.cpp',
     'nsMaiInterfaceHypertext.cpp',
     'nsMaiInterfaceImage.cpp',
     'nsMaiInterfaceSelection.cpp',
     'nsMaiInterfaceTable.cpp',
+    'nsMaiInterfaceTableCell.cpp',
     'nsMaiInterfaceText.cpp',
     'nsMaiInterfaceValue.cpp',
     'Platform.cpp',
     'RootAccessibleWrap.cpp',
     'UtilInterface.cpp',
 ]
 
 LOCAL_INCLUDES += [
new file mode 100644
--- /dev/null
+++ b/accessible/atk/nsMaiInterfaceTableCell.cpp
@@ -0,0 +1,216 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "InterfaceInitFuncs.h"
+
+#include "Accessible-inl.h"
+#include "AccessibleWrap.h"
+#include "nsAccUtils.h"
+#include "TableAccessible.h"
+#include "TableCellAccessible.h"
+#include "nsMai.h"
+#include "ProxyAccessible.h"
+#include "nsArrayUtils.h"
+
+#include "mozilla/Likely.h"
+
+using namespace mozilla::a11y;
+
+extern "C" {
+static gint
+GetColumnSpanCB(AtkTableCell* aCell)
+{
+  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aCell));
+  if (accWrap) {
+    return accWrap->AsTableCell()->ColExtent();
+  }
+
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aCell))) {
+    return proxy->ColExtent();
+  }
+
+  return 0;
+}
+
+static gboolean
+GetRowSpanCB(AtkTableCell* aCell)
+{
+  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aCell));
+  if (accWrap) {
+    return accWrap->AsTableCell()->RowExtent();
+  }
+
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aCell))) {
+    return proxy->RowExtent();
+  }
+
+  return 0;
+}
+
+static gboolean
+GetPositionCB(AtkTableCell* aCell, gint* aRow, gint* aCol)
+{
+  if (AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aCell))) {
+    TableCellAccessible* cell = accWrap->AsTableCell();
+    *aRow = cell->RowIdx();
+    *aCol = cell->ColIdx();
+    return true;
+  }
+
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aCell))) {
+    uint32_t rowIdx = 0, colIdx = 0;
+    proxy->GetPosition(&rowIdx, &colIdx);
+    *aCol = colIdx;
+    *aRow = rowIdx;
+    return true;
+  }
+
+  return false;
+}
+
+static gboolean
+GetColumnRowSpanCB(AtkTableCell* aCell, gint* aCol, gint* aRow,
+                   gint* aColExtent, gint* aRowExtent) {
+  if (AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aCell))) {
+    TableCellAccessible* cellAcc = accWrap->AsTableCell();
+    *aCol = cellAcc->ColIdx();
+    *aRow = cellAcc->RowIdx();
+    *aColExtent = cellAcc->ColExtent();
+    *aRowExtent = cellAcc->ColExtent();
+    return true;
+  }
+
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aCell))) {
+    uint32_t colIdx = 0, rowIdx = 0, colExtent = 0, rowExtent = 0;
+    proxy->GetColRowExtents(&colIdx, &rowIdx, &colExtent, &rowExtent);
+    *aCol = colIdx;
+    *aRow = rowIdx;
+    *aColExtent = colExtent;
+    *aRowExtent = rowExtent;
+  return true;
+  }
+
+  return false;
+}
+
+static AtkObject*
+GetTableCB(AtkTableCell* aTableCell)
+{
+  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTableCell));
+  if (accWrap) {
+    TableAccessible* table = accWrap->AsTableCell()->Table();
+    if (!table) {
+      return nullptr;
+    }
+
+    Accessible* tableAcc = table->AsAccessible();
+    return tableAcc ? AccessibleWrap::GetAtkObject(tableAcc) : nullptr;
+  }
+
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTableCell))) {
+    ProxyAccessible* table = proxy->TableOfACell();
+    return table ? GetWrapperFor(table) : nullptr;
+  }
+
+  return nullptr;
+}
+
+static GPtrArray*
+GetColumnHeaderCellsCB(AtkTableCell* aCell)
+{
+  if (AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aCell))) {
+    AutoTArray<Accessible*, 10> headers;
+    accWrap->AsTableCell()->ColHeaderCells(&headers);
+    if (headers.IsEmpty()) {
+      return nullptr;
+    }
+
+    GPtrArray* atkHeaders = g_ptr_array_sized_new(headers.Length());
+    for (Accessible* header: headers) {
+      AtkObject* atkHeader = AccessibleWrap::GetAtkObject(header);
+      g_object_ref(atkHeader);
+      g_ptr_array_add(atkHeaders, atkHeader);
+    }
+
+    return atkHeaders;
+  }
+
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aCell))) {
+    AutoTArray<ProxyAccessible*, 10> headers;
+    proxy->ColHeaderCells(&headers);
+    if (headers.IsEmpty()) {
+      return nullptr;
+    }
+
+    GPtrArray* atkHeaders = g_ptr_array_sized_new(headers.Length());
+    for (ProxyAccessible* header: headers) {
+      AtkObject* atkHeader = GetWrapperFor(header);
+      g_object_ref(atkHeader);
+      g_ptr_array_add(atkHeaders, atkHeader);
+    }
+
+    return atkHeaders;
+  }
+
+  return nullptr;
+}
+
+static GPtrArray*
+GetRowHeaderCellsCB(AtkTableCell* aCell)
+{
+  if (AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aCell))) {
+    AutoTArray<Accessible*, 10> headers;
+    accWrap->AsTableCell()->RowHeaderCells(&headers);
+    if (headers.IsEmpty()) {
+      return nullptr;
+    }
+
+    GPtrArray* atkHeaders = g_ptr_array_sized_new(headers.Length());
+    for (Accessible* header: headers) {
+      AtkObject* atkHeader = AccessibleWrap::GetAtkObject(header);
+      g_object_ref(atkHeader);
+      g_ptr_array_add(atkHeaders, atkHeader);
+    }
+
+    return atkHeaders;
+  }
+
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aCell))) {
+    AutoTArray<ProxyAccessible*, 10> headers;
+    proxy->RowHeaderCells(&headers);
+    if (headers.IsEmpty()) {
+      return nullptr;
+    }
+
+    GPtrArray* atkHeaders = g_ptr_array_sized_new(headers.Length());
+    for (ProxyAccessible* header: headers) {
+      AtkObject* atkHeader = GetWrapperFor(header);
+      g_object_ref(atkHeader);
+      g_ptr_array_add(atkHeaders, atkHeader);
+    }
+
+    return atkHeaders;
+  }
+
+  return nullptr;
+}
+}
+
+void
+tableCellInterfaceInitCB(AtkTableCellIface* aIface)
+{
+  NS_ASSERTION(aIface, "no interface!");
+  if (MOZ_UNLIKELY(!aIface))
+    return;
+
+  aIface->get_column_span = GetColumnSpanCB;
+  aIface->get_column_header_cells = GetColumnHeaderCellsCB;
+  aIface->get_position = GetPositionCB;
+  aIface->get_row_span = GetRowSpanCB;
+  aIface->get_row_header_cells = GetRowHeaderCellsCB;
+  aIface->get_row_column_span = GetColumnRowSpanCB;
+  aIface->get_table = GetTableCB;
+}