nsMaiInterfaceTable.cpp (7367B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "InterfaceInitFuncs.h" 8 9 #include "AccessibleWrap.h" 10 #include "mozilla/a11y/TableAccessible.h" 11 #include "nsAccessibilityService.h" 12 #include "nsMai.h" 13 #include "RemoteAccessible.h" 14 #include "nsTArray.h" 15 16 #include "mozilla/Likely.h" 17 18 using namespace mozilla; 19 using namespace mozilla::a11y; 20 21 extern "C" { 22 static AtkObject* refAtCB(AtkTable* aTable, gint aRowIdx, gint aColIdx) { 23 if (aRowIdx < 0 || aColIdx < 0) { 24 return nullptr; 25 } 26 27 AtkObject* cellAtkObj = nullptr; 28 Accessible* acc = GetInternalObj(ATK_OBJECT(aTable)); 29 if (!acc) { 30 return nullptr; 31 } 32 Accessible* cell = acc->AsTable()->CellAt(aRowIdx, aColIdx); 33 if (!cell) { 34 return nullptr; 35 } 36 37 cellAtkObj = GetWrapperFor(cell); 38 39 if (cellAtkObj) { 40 g_object_ref(cellAtkObj); 41 } 42 43 return cellAtkObj; 44 } 45 46 static gint getIndexAtCB(AtkTable* aTable, gint aRowIdx, gint aColIdx) { 47 if (aRowIdx < 0 || aColIdx < 0) { 48 return -1; 49 } 50 51 Accessible* acc = GetInternalObj(ATK_OBJECT(aTable)); 52 if (!acc) { 53 return -1; 54 } 55 return static_cast<gint>(acc->AsTable()->CellIndexAt(aRowIdx, aColIdx)); 56 } 57 58 static gint getColumnAtIndexCB(AtkTable* aTable, gint aIdx) { 59 if (aIdx < 0) { 60 return -1; 61 } 62 63 Accessible* acc = GetInternalObj(ATK_OBJECT(aTable)); 64 if (!acc) { 65 return -1; 66 } 67 return static_cast<gint>(acc->AsTable()->ColIndexAt(aIdx)); 68 } 69 70 static gint getRowAtIndexCB(AtkTable* aTable, gint aIdx) { 71 if (aIdx < 0) { 72 return -1; 73 } 74 75 Accessible* acc = GetInternalObj(ATK_OBJECT(aTable)); 76 if (!acc) { 77 return -1; 78 } 79 return static_cast<gint>(acc->AsTable()->RowIndexAt(aIdx)); 80 } 81 82 static gint getColumnCountCB(AtkTable* aTable) { 83 Accessible* acc = GetInternalObj(ATK_OBJECT(aTable)); 84 if (!acc) { 85 return -1; 86 } 87 return static_cast<gint>(acc->AsTable()->ColCount()); 88 } 89 90 static gint getRowCountCB(AtkTable* aTable) { 91 Accessible* acc = GetInternalObj(ATK_OBJECT(aTable)); 92 if (!acc) { 93 return -1; 94 } 95 return static_cast<gint>(acc->AsTable()->RowCount()); 96 } 97 98 static gint getColumnExtentAtCB(AtkTable* aTable, gint aRowIdx, gint aColIdx) { 99 if (aRowIdx < 0 || aColIdx < 0) { 100 return -1; 101 } 102 103 Accessible* acc = GetInternalObj(ATK_OBJECT(aTable)); 104 if (!acc) { 105 return -1; 106 } 107 return static_cast<gint>(acc->AsTable()->ColExtentAt(aRowIdx, aColIdx)); 108 } 109 110 static gint getRowExtentAtCB(AtkTable* aTable, gint aRowIdx, gint aColIdx) { 111 Accessible* acc = GetInternalObj(ATK_OBJECT(aTable)); 112 if (!acc) { 113 return -1; 114 } 115 return static_cast<gint>(acc->AsTable()->RowExtentAt(aRowIdx, aColIdx)); 116 } 117 118 static AtkObject* getCaptionCB(AtkTable* aTable) { 119 Accessible* acc = GetInternalObj(ATK_OBJECT(aTable)); 120 if (!acc) { 121 return nullptr; 122 } 123 Accessible* caption = acc->AsTable()->Caption(); 124 return caption ? GetWrapperFor(caption) : nullptr; 125 } 126 127 static const gchar* getColumnDescriptionCB(AtkTable* aTable, gint aColumn) { 128 Accessible* acc = GetInternalObj(ATK_OBJECT(aTable)); 129 if (!acc) { 130 return nullptr; 131 } 132 nsAutoString autoStr; 133 acc->AsTable()->ColDescription(aColumn, autoStr); 134 return AccessibleWrap::ReturnString(autoStr); 135 } 136 137 static AtkObject* getColumnHeaderCB(AtkTable* aTable, gint aColIdx) { 138 Accessible* acc = GetInternalObj(ATK_OBJECT(aTable)); 139 if (!acc) { 140 return nullptr; 141 } 142 Accessible* header = AccessibleWrap::GetColumnHeader(acc->AsTable(), aColIdx); 143 return header ? GetWrapperFor(header) : nullptr; 144 } 145 146 static const gchar* getRowDescriptionCB(AtkTable* aTable, gint aRow) { 147 Accessible* acc = GetInternalObj(ATK_OBJECT(aTable)); 148 if (!acc) { 149 return nullptr; 150 } 151 nsAutoString autoStr; 152 acc->AsTable()->RowDescription(aRow, autoStr); 153 return AccessibleWrap::ReturnString(autoStr); 154 } 155 156 static AtkObject* getRowHeaderCB(AtkTable* aTable, gint aRowIdx) { 157 Accessible* acc = GetInternalObj(ATK_OBJECT(aTable)); 158 if (!acc) { 159 return nullptr; 160 } 161 Accessible* header = AccessibleWrap::GetRowHeader(acc->AsTable(), aRowIdx); 162 return header ? GetWrapperFor(header) : nullptr; 163 } 164 165 static AtkObject* getSummaryCB(AtkTable* aTable) { 166 // Neither html:table nor xul:tree nor ARIA grid/tree have an ability to 167 // link an accessible object to specify a summary. There is closes method 168 // in TableAccessible::summary to get a summary as a string which is not 169 // mapped directly to ATK. 170 return nullptr; 171 } 172 173 static gint getSelectedColumnsCB(AtkTable* aTable, gint** aSelected) { 174 *aSelected = nullptr; 175 176 Accessible* acc = GetInternalObj(ATK_OBJECT(aTable)); 177 if (!acc) { 178 return 0; 179 } 180 AutoTArray<uint32_t, 10> cols; 181 acc->AsTable()->SelectedColIndices(&cols); 182 183 if (cols.IsEmpty()) return 0; 184 185 gint* atkColumns = g_new(gint, cols.Length()); 186 if (!atkColumns) { 187 NS_WARNING("OUT OF MEMORY"); 188 return 0; 189 } 190 191 memcpy(atkColumns, cols.Elements(), cols.Length() * sizeof(uint32_t)); 192 *aSelected = atkColumns; 193 return cols.Length(); 194 } 195 196 static gint getSelectedRowsCB(AtkTable* aTable, gint** aSelected) { 197 Accessible* acc = GetInternalObj(ATK_OBJECT(aTable)); 198 if (!acc) { 199 return 0; 200 } 201 AutoTArray<uint32_t, 10> rows; 202 acc->AsTable()->SelectedRowIndices(&rows); 203 204 gint* atkRows = g_new(gint, rows.Length()); 205 if (!atkRows) { 206 NS_WARNING("OUT OF MEMORY"); 207 return 0; 208 } 209 210 memcpy(atkRows, rows.Elements(), rows.Length() * sizeof(uint32_t)); 211 *aSelected = atkRows; 212 return rows.Length(); 213 } 214 215 static gboolean isColumnSelectedCB(AtkTable* aTable, gint aColIdx) { 216 Accessible* acc = GetInternalObj(ATK_OBJECT(aTable)); 217 if (!acc) { 218 return FALSE; 219 } 220 return static_cast<gboolean>(acc->AsTable()->IsColSelected(aColIdx)); 221 } 222 223 static gboolean isRowSelectedCB(AtkTable* aTable, gint aRowIdx) { 224 Accessible* acc = GetInternalObj(ATK_OBJECT(aTable)); 225 if (!acc) { 226 return FALSE; 227 } 228 return static_cast<gboolean>(acc->AsTable()->IsRowSelected(aRowIdx)); 229 } 230 231 static gboolean isCellSelectedCB(AtkTable* aTable, gint aRowIdx, gint aColIdx) { 232 Accessible* acc = GetInternalObj(ATK_OBJECT(aTable)); 233 if (!acc) { 234 return FALSE; 235 } 236 return static_cast<gboolean>( 237 acc->AsTable()->IsCellSelected(aRowIdx, aColIdx)); 238 } 239 } 240 241 void tableInterfaceInitCB(AtkTableIface* aIface) { 242 NS_ASSERTION(aIface, "no interface!"); 243 if (MOZ_UNLIKELY(!aIface)) return; 244 245 aIface->ref_at = refAtCB; 246 aIface->get_index_at = getIndexAtCB; 247 aIface->get_column_at_index = getColumnAtIndexCB; 248 aIface->get_row_at_index = getRowAtIndexCB; 249 aIface->get_n_columns = getColumnCountCB; 250 aIface->get_n_rows = getRowCountCB; 251 aIface->get_column_extent_at = getColumnExtentAtCB; 252 aIface->get_row_extent_at = getRowExtentAtCB; 253 aIface->get_caption = getCaptionCB; 254 aIface->get_column_description = getColumnDescriptionCB; 255 aIface->get_column_header = getColumnHeaderCB; 256 aIface->get_row_description = getRowDescriptionCB; 257 aIface->get_row_header = getRowHeaderCB; 258 aIface->get_summary = getSummaryCB; 259 aIface->get_selected_columns = getSelectedColumnsCB; 260 aIface->get_selected_rows = getSelectedRowsCB; 261 aIface->is_column_selected = isColumnSelectedCB; 262 aIface->is_row_selected = isRowSelectedCB; 263 aIface->is_selected = isCellSelectedCB; 264 }