accessible/src/xul/XULListboxAccessible.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "XULListboxAccessible.h"
michael@0 7
michael@0 8 #include "Accessible-inl.h"
michael@0 9 #include "nsAccessibilityService.h"
michael@0 10 #include "nsAccUtils.h"
michael@0 11 #include "DocAccessible.h"
michael@0 12 #include "Role.h"
michael@0 13 #include "States.h"
michael@0 14
michael@0 15 #include "nsComponentManagerUtils.h"
michael@0 16 #include "nsIAutoCompleteInput.h"
michael@0 17 #include "nsIAutoCompletePopup.h"
michael@0 18 #include "nsIDOMXULMenuListElement.h"
michael@0 19 #include "nsIDOMXULMultSelectCntrlEl.h"
michael@0 20 #include "nsIDOMNodeList.h"
michael@0 21 #include "nsIDOMXULPopupElement.h"
michael@0 22 #include "nsIDOMXULSelectCntrlItemEl.h"
michael@0 23 #include "nsIMutableArray.h"
michael@0 24 #include "nsIPersistentProperties2.h"
michael@0 25
michael@0 26 using namespace mozilla::a11y;
michael@0 27
michael@0 28 ////////////////////////////////////////////////////////////////////////////////
michael@0 29 // XULColumAccessible
michael@0 30 ////////////////////////////////////////////////////////////////////////////////
michael@0 31
michael@0 32 XULColumAccessible::
michael@0 33 XULColumAccessible(nsIContent* aContent, DocAccessible* aDoc) :
michael@0 34 AccessibleWrap(aContent, aDoc)
michael@0 35 {
michael@0 36 }
michael@0 37
michael@0 38 role
michael@0 39 XULColumAccessible::NativeRole()
michael@0 40 {
michael@0 41 return roles::LIST;
michael@0 42 }
michael@0 43
michael@0 44 uint64_t
michael@0 45 XULColumAccessible::NativeState()
michael@0 46 {
michael@0 47 return states::READONLY;
michael@0 48 }
michael@0 49
michael@0 50
michael@0 51 ////////////////////////////////////////////////////////////////////////////////
michael@0 52 // XULColumnItemAccessible
michael@0 53 ////////////////////////////////////////////////////////////////////////////////
michael@0 54
michael@0 55 XULColumnItemAccessible::
michael@0 56 XULColumnItemAccessible(nsIContent* aContent, DocAccessible* aDoc) :
michael@0 57 LeafAccessible(aContent, aDoc)
michael@0 58 {
michael@0 59 }
michael@0 60
michael@0 61 role
michael@0 62 XULColumnItemAccessible::NativeRole()
michael@0 63 {
michael@0 64 return roles::COLUMNHEADER;
michael@0 65 }
michael@0 66
michael@0 67 uint64_t
michael@0 68 XULColumnItemAccessible::NativeState()
michael@0 69 {
michael@0 70 return states::READONLY;
michael@0 71 }
michael@0 72
michael@0 73 uint8_t
michael@0 74 XULColumnItemAccessible::ActionCount()
michael@0 75 {
michael@0 76 return 1;
michael@0 77 }
michael@0 78
michael@0 79 NS_IMETHODIMP
michael@0 80 XULColumnItemAccessible::GetActionName(uint8_t aIndex, nsAString& aName)
michael@0 81 {
michael@0 82 if (aIndex != eAction_Click)
michael@0 83 return NS_ERROR_INVALID_ARG;
michael@0 84
michael@0 85 aName.AssignLiteral("click");
michael@0 86 return NS_OK;
michael@0 87 }
michael@0 88
michael@0 89 NS_IMETHODIMP
michael@0 90 XULColumnItemAccessible::DoAction(uint8_t aIndex)
michael@0 91 {
michael@0 92 if (aIndex != eAction_Click)
michael@0 93 return NS_ERROR_INVALID_ARG;
michael@0 94
michael@0 95 DoCommand();
michael@0 96 return NS_OK;
michael@0 97 }
michael@0 98
michael@0 99 ////////////////////////////////////////////////////////////////////////////////
michael@0 100 // XULListboxAccessible
michael@0 101 ////////////////////////////////////////////////////////////////////////////////
michael@0 102
michael@0 103 XULListboxAccessible::
michael@0 104 XULListboxAccessible(nsIContent* aContent, DocAccessible* aDoc) :
michael@0 105 XULSelectControlAccessible(aContent, aDoc), xpcAccessibleTable(this)
michael@0 106 {
michael@0 107 nsIContent* parentContent = mContent->GetFlattenedTreeParent();
michael@0 108 if (parentContent) {
michael@0 109 nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
michael@0 110 do_QueryInterface(parentContent);
michael@0 111 if (autoCompletePopupElm)
michael@0 112 mGenericTypes |= eAutoCompletePopup;
michael@0 113 }
michael@0 114 }
michael@0 115
michael@0 116 NS_IMPL_ADDREF_INHERITED(XULListboxAccessible, XULSelectControlAccessible)
michael@0 117 NS_IMPL_RELEASE_INHERITED(XULListboxAccessible, XULSelectControlAccessible)
michael@0 118
michael@0 119 nsresult
michael@0 120 XULListboxAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
michael@0 121 {
michael@0 122 nsresult rv = XULSelectControlAccessible::QueryInterface(aIID, aInstancePtr);
michael@0 123 if (*aInstancePtr)
michael@0 124 return rv;
michael@0 125
michael@0 126 if (aIID.Equals(NS_GET_IID(nsIAccessibleTable)) && IsMulticolumn()) {
michael@0 127 *aInstancePtr = static_cast<nsIAccessibleTable*>(this);
michael@0 128 NS_ADDREF_THIS();
michael@0 129 return NS_OK;
michael@0 130 }
michael@0 131
michael@0 132 return NS_ERROR_NO_INTERFACE;
michael@0 133 }
michael@0 134
michael@0 135 ////////////////////////////////////////////////////////////////////////////////
michael@0 136 // Accessible
michael@0 137
michael@0 138 void
michael@0 139 XULListboxAccessible::Shutdown()
michael@0 140 {
michael@0 141 mTable = nullptr;
michael@0 142 XULSelectControlAccessible::Shutdown();
michael@0 143 }
michael@0 144
michael@0 145 bool
michael@0 146 XULListboxAccessible::IsMulticolumn()
michael@0 147 {
michael@0 148 int32_t numColumns = 0;
michael@0 149 nsresult rv = GetColumnCount(&numColumns);
michael@0 150 if (NS_FAILED(rv))
michael@0 151 return false;
michael@0 152
michael@0 153 return numColumns > 1;
michael@0 154 }
michael@0 155
michael@0 156 ////////////////////////////////////////////////////////////////////////////////
michael@0 157 // XULListboxAccessible. nsIAccessible
michael@0 158
michael@0 159 uint64_t
michael@0 160 XULListboxAccessible::NativeState()
michael@0 161 {
michael@0 162 // As a XULListboxAccessible we can have the following states:
michael@0 163 // FOCUSED, READONLY, FOCUSABLE
michael@0 164
michael@0 165 // Get focus status from base class
michael@0 166 uint64_t states = Accessible::NativeState();
michael@0 167
michael@0 168 // see if we are multiple select if so set ourselves as such
michael@0 169
michael@0 170 if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::seltype,
michael@0 171 nsGkAtoms::multiple, eCaseMatters)) {
michael@0 172 states |= states::MULTISELECTABLE | states::EXTSELECTABLE;
michael@0 173 }
michael@0 174
michael@0 175 return states;
michael@0 176 }
michael@0 177
michael@0 178 /**
michael@0 179 * Our value is the label of our ( first ) selected child.
michael@0 180 */
michael@0 181 void
michael@0 182 XULListboxAccessible::Value(nsString& aValue)
michael@0 183 {
michael@0 184 aValue.Truncate();
michael@0 185
michael@0 186 nsCOMPtr<nsIDOMXULSelectControlElement> select(do_QueryInterface(mContent));
michael@0 187 if (select) {
michael@0 188 nsCOMPtr<nsIDOMXULSelectControlItemElement> selectedItem;
michael@0 189 select->GetSelectedItem(getter_AddRefs(selectedItem));
michael@0 190 if (selectedItem)
michael@0 191 selectedItem->GetLabel(aValue);
michael@0 192 }
michael@0 193 }
michael@0 194
michael@0 195 role
michael@0 196 XULListboxAccessible::NativeRole()
michael@0 197 {
michael@0 198 // A richlistbox is used with the new autocomplete URL bar, and has a parent
michael@0 199 // popup <panel>.
michael@0 200 nsCOMPtr<nsIDOMXULPopupElement> xulPopup =
michael@0 201 do_QueryInterface(mContent->GetParent());
michael@0 202 if (xulPopup)
michael@0 203 return roles::COMBOBOX_LIST;
michael@0 204
michael@0 205 return IsMulticolumn() ? roles::TABLE : roles::LISTBOX;
michael@0 206 }
michael@0 207
michael@0 208 ////////////////////////////////////////////////////////////////////////////////
michael@0 209 // XULListboxAccessible. nsIAccessibleTable
michael@0 210
michael@0 211 uint32_t
michael@0 212 XULListboxAccessible::ColCount()
michael@0 213 {
michael@0 214 nsIContent* headContent = nullptr;
michael@0 215 for (nsIContent* childContent = mContent->GetFirstChild(); childContent;
michael@0 216 childContent = childContent->GetNextSibling()) {
michael@0 217 if (childContent->NodeInfo()->Equals(nsGkAtoms::listcols,
michael@0 218 kNameSpaceID_XUL)) {
michael@0 219 headContent = childContent;
michael@0 220 }
michael@0 221 }
michael@0 222 if (!headContent)
michael@0 223 return 0;
michael@0 224
michael@0 225 uint32_t columnCount = 0;
michael@0 226 for (nsIContent* childContent = headContent->GetFirstChild(); childContent;
michael@0 227 childContent = childContent->GetNextSibling()) {
michael@0 228 if (childContent->NodeInfo()->Equals(nsGkAtoms::listcol,
michael@0 229 kNameSpaceID_XUL)) {
michael@0 230 columnCount++;
michael@0 231 }
michael@0 232 }
michael@0 233
michael@0 234 return columnCount;
michael@0 235 }
michael@0 236
michael@0 237 uint32_t
michael@0 238 XULListboxAccessible::RowCount()
michael@0 239 {
michael@0 240 nsCOMPtr<nsIDOMXULSelectControlElement> element(do_QueryInterface(mContent));
michael@0 241
michael@0 242 uint32_t itemCount = 0;
michael@0 243 if(element)
michael@0 244 element->GetItemCount(&itemCount);
michael@0 245
michael@0 246 return itemCount;
michael@0 247 }
michael@0 248
michael@0 249 Accessible*
michael@0 250 XULListboxAccessible::CellAt(uint32_t aRowIndex, uint32_t aColumnIndex)
michael@0 251 {
michael@0 252 nsCOMPtr<nsIDOMXULSelectControlElement> control =
michael@0 253 do_QueryInterface(mContent);
michael@0 254 NS_ENSURE_TRUE(control, nullptr);
michael@0 255
michael@0 256 nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
michael@0 257 control->GetItemAtIndex(aRowIndex, getter_AddRefs(item));
michael@0 258 if (!item)
michael@0 259 return nullptr;
michael@0 260
michael@0 261 nsCOMPtr<nsIContent> itemContent(do_QueryInterface(item));
michael@0 262 if (!itemContent)
michael@0 263 return nullptr;
michael@0 264
michael@0 265 Accessible* row = mDoc->GetAccessible(itemContent);
michael@0 266 NS_ENSURE_TRUE(row, nullptr);
michael@0 267
michael@0 268 return row->GetChildAt(aColumnIndex);
michael@0 269 }
michael@0 270
michael@0 271 bool
michael@0 272 XULListboxAccessible::IsColSelected(uint32_t aColIdx)
michael@0 273 {
michael@0 274 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
michael@0 275 do_QueryInterface(mContent);
michael@0 276 NS_ASSERTION(control,
michael@0 277 "Doesn't implement nsIDOMXULMultiSelectControlElement.");
michael@0 278
michael@0 279 int32_t selectedrowCount = 0;
michael@0 280 nsresult rv = control->GetSelectedCount(&selectedrowCount);
michael@0 281 NS_ENSURE_SUCCESS(rv, false);
michael@0 282
michael@0 283 return selectedrowCount == RowCount();
michael@0 284 }
michael@0 285
michael@0 286 bool
michael@0 287 XULListboxAccessible::IsRowSelected(uint32_t aRowIdx)
michael@0 288 {
michael@0 289 nsCOMPtr<nsIDOMXULSelectControlElement> control =
michael@0 290 do_QueryInterface(mContent);
michael@0 291 NS_ASSERTION(control,
michael@0 292 "Doesn't implement nsIDOMXULSelectControlElement.");
michael@0 293
michael@0 294 nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
michael@0 295 nsresult rv = control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
michael@0 296 NS_ENSURE_SUCCESS(rv, false);
michael@0 297
michael@0 298 bool isSelected = false;
michael@0 299 item->GetSelected(&isSelected);
michael@0 300 return isSelected;
michael@0 301 }
michael@0 302
michael@0 303 bool
michael@0 304 XULListboxAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx)
michael@0 305 {
michael@0 306 return IsRowSelected(aRowIdx);
michael@0 307 }
michael@0 308
michael@0 309 uint32_t
michael@0 310 XULListboxAccessible::SelectedCellCount()
michael@0 311 {
michael@0 312 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
michael@0 313 do_QueryInterface(mContent);
michael@0 314 NS_ASSERTION(control,
michael@0 315 "Doesn't implement nsIDOMXULMultiSelectControlElement.");
michael@0 316
michael@0 317 nsCOMPtr<nsIDOMNodeList> selectedItems;
michael@0 318 control->GetSelectedItems(getter_AddRefs(selectedItems));
michael@0 319 if (!selectedItems)
michael@0 320 return 0;
michael@0 321
michael@0 322 uint32_t selectedItemsCount = 0;
michael@0 323 nsresult rv = selectedItems->GetLength(&selectedItemsCount);
michael@0 324 NS_ENSURE_SUCCESS(rv, 0);
michael@0 325
michael@0 326 return selectedItemsCount * ColCount();
michael@0 327 }
michael@0 328
michael@0 329 uint32_t
michael@0 330 XULListboxAccessible::SelectedColCount()
michael@0 331 {
michael@0 332 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
michael@0 333 do_QueryInterface(mContent);
michael@0 334 NS_ASSERTION(control,
michael@0 335 "Doesn't implement nsIDOMXULMultiSelectControlElement.");
michael@0 336
michael@0 337 int32_t selectedRowCount = 0;
michael@0 338 nsresult rv = control->GetSelectedCount(&selectedRowCount);
michael@0 339 NS_ENSURE_SUCCESS(rv, 0);
michael@0 340
michael@0 341 return selectedRowCount > 0 && selectedRowCount == RowCount() ? ColCount() : 0;
michael@0 342 }
michael@0 343
michael@0 344 uint32_t
michael@0 345 XULListboxAccessible::SelectedRowCount()
michael@0 346 {
michael@0 347 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
michael@0 348 do_QueryInterface(mContent);
michael@0 349 NS_ASSERTION(control,
michael@0 350 "Doesn't implement nsIDOMXULMultiSelectControlElement.");
michael@0 351
michael@0 352 int32_t selectedRowCount = 0;
michael@0 353 nsresult rv = control->GetSelectedCount(&selectedRowCount);
michael@0 354 NS_ENSURE_SUCCESS(rv, 0);
michael@0 355
michael@0 356 return selectedRowCount >= 0 ? selectedRowCount : 0;
michael@0 357 }
michael@0 358
michael@0 359 void
michael@0 360 XULListboxAccessible::SelectedCells(nsTArray<Accessible*>* aCells)
michael@0 361 {
michael@0 362 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
michael@0 363 do_QueryInterface(mContent);
michael@0 364 NS_ASSERTION(control,
michael@0 365 "Doesn't implement nsIDOMXULMultiSelectControlElement.");
michael@0 366
michael@0 367 nsCOMPtr<nsIDOMNodeList> selectedItems;
michael@0 368 control->GetSelectedItems(getter_AddRefs(selectedItems));
michael@0 369 if (!selectedItems)
michael@0 370 return;
michael@0 371
michael@0 372 uint32_t selectedItemsCount = 0;
michael@0 373 DebugOnly<nsresult> rv = selectedItems->GetLength(&selectedItemsCount);
michael@0 374 NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!");
michael@0 375
michael@0 376 for (uint32_t index = 0; index < selectedItemsCount; index++) {
michael@0 377 nsCOMPtr<nsIDOMNode> itemNode;
michael@0 378 selectedItems->Item(index, getter_AddRefs(itemNode));
michael@0 379 nsCOMPtr<nsIContent> itemContent(do_QueryInterface(itemNode));
michael@0 380 Accessible* item = mDoc->GetAccessible(itemContent);
michael@0 381
michael@0 382 if (item) {
michael@0 383 uint32_t cellCount = item->ChildCount();
michael@0 384 for (uint32_t cellIdx = 0; cellIdx < cellCount; cellIdx++) {
michael@0 385 Accessible* cell = mChildren[cellIdx];
michael@0 386 if (cell->Role() == roles::CELL)
michael@0 387 aCells->AppendElement(cell);
michael@0 388 }
michael@0 389 }
michael@0 390 }
michael@0 391 }
michael@0 392
michael@0 393 void
michael@0 394 XULListboxAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells)
michael@0 395 {
michael@0 396 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
michael@0 397 do_QueryInterface(mContent);
michael@0 398 NS_ASSERTION(control,
michael@0 399 "Doesn't implement nsIDOMXULMultiSelectControlElement.");
michael@0 400
michael@0 401 nsCOMPtr<nsIDOMNodeList> selectedItems;
michael@0 402 control->GetSelectedItems(getter_AddRefs(selectedItems));
michael@0 403 if (!selectedItems)
michael@0 404 return;
michael@0 405
michael@0 406 uint32_t selectedItemsCount = 0;
michael@0 407 DebugOnly<nsresult> rv = selectedItems->GetLength(&selectedItemsCount);
michael@0 408 NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!");
michael@0 409
michael@0 410 uint32_t colCount = ColCount();
michael@0 411 aCells->SetCapacity(selectedItemsCount * colCount);
michael@0 412 aCells->AppendElements(selectedItemsCount * colCount);
michael@0 413
michael@0 414 for (uint32_t selItemsIdx = 0, cellsIdx = 0;
michael@0 415 selItemsIdx < selectedItemsCount; selItemsIdx++) {
michael@0 416
michael@0 417 nsCOMPtr<nsIDOMNode> itemNode;
michael@0 418 selectedItems->Item(selItemsIdx, getter_AddRefs(itemNode));
michael@0 419 nsCOMPtr<nsIDOMXULSelectControlItemElement> item =
michael@0 420 do_QueryInterface(itemNode);
michael@0 421
michael@0 422 if (item) {
michael@0 423 int32_t itemIdx = -1;
michael@0 424 control->GetIndexOfItem(item, &itemIdx);
michael@0 425 if (itemIdx >= 0)
michael@0 426 for (uint32_t colIdx = 0; colIdx < colCount; colIdx++, cellsIdx++)
michael@0 427 aCells->ElementAt(cellsIdx) = itemIdx * colCount + colIdx;
michael@0 428 }
michael@0 429 }
michael@0 430 }
michael@0 431
michael@0 432 void
michael@0 433 XULListboxAccessible::SelectedColIndices(nsTArray<uint32_t>* aCols)
michael@0 434 {
michael@0 435 uint32_t selColCount = SelectedColCount();
michael@0 436 aCols->SetCapacity(selColCount);
michael@0 437
michael@0 438 for (uint32_t colIdx = 0; colIdx < selColCount; colIdx++)
michael@0 439 aCols->AppendElement(colIdx);
michael@0 440 }
michael@0 441
michael@0 442 void
michael@0 443 XULListboxAccessible::SelectedRowIndices(nsTArray<uint32_t>* aRows)
michael@0 444 {
michael@0 445 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
michael@0 446 do_QueryInterface(mContent);
michael@0 447 NS_ASSERTION(control,
michael@0 448 "Doesn't implement nsIDOMXULMultiSelectControlElement.");
michael@0 449
michael@0 450 nsCOMPtr<nsIDOMNodeList> selectedItems;
michael@0 451 control->GetSelectedItems(getter_AddRefs(selectedItems));
michael@0 452 if (!selectedItems)
michael@0 453 return;
michael@0 454
michael@0 455 uint32_t rowCount = 0;
michael@0 456 DebugOnly<nsresult> rv = selectedItems->GetLength(&rowCount);
michael@0 457 NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!");
michael@0 458
michael@0 459 if (!rowCount)
michael@0 460 return;
michael@0 461
michael@0 462 aRows->SetCapacity(rowCount);
michael@0 463 aRows->AppendElements(rowCount);
michael@0 464
michael@0 465 for (uint32_t rowIdx = 0; rowIdx < rowCount; rowIdx++) {
michael@0 466 nsCOMPtr<nsIDOMNode> itemNode;
michael@0 467 selectedItems->Item(rowIdx, getter_AddRefs(itemNode));
michael@0 468 nsCOMPtr<nsIDOMXULSelectControlItemElement> item =
michael@0 469 do_QueryInterface(itemNode);
michael@0 470
michael@0 471 if (item) {
michael@0 472 int32_t itemIdx = -1;
michael@0 473 control->GetIndexOfItem(item, &itemIdx);
michael@0 474 if (itemIdx >= 0)
michael@0 475 aRows->ElementAt(rowIdx) = itemIdx;
michael@0 476 }
michael@0 477 }
michael@0 478 }
michael@0 479
michael@0 480 void
michael@0 481 XULListboxAccessible::SelectRow(uint32_t aRowIdx)
michael@0 482 {
michael@0 483 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
michael@0 484 do_QueryInterface(mContent);
michael@0 485 NS_ASSERTION(control,
michael@0 486 "Doesn't implement nsIDOMXULMultiSelectControlElement.");
michael@0 487
michael@0 488 nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
michael@0 489 control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
michael@0 490 control->SelectItem(item);
michael@0 491 }
michael@0 492
michael@0 493 void
michael@0 494 XULListboxAccessible::UnselectRow(uint32_t aRowIdx)
michael@0 495 {
michael@0 496 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
michael@0 497 do_QueryInterface(mContent);
michael@0 498 NS_ASSERTION(control,
michael@0 499 "Doesn't implement nsIDOMXULMultiSelectControlElement.");
michael@0 500
michael@0 501 nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
michael@0 502 control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
michael@0 503 control->RemoveItemFromSelection(item);
michael@0 504 }
michael@0 505
michael@0 506 ////////////////////////////////////////////////////////////////////////////////
michael@0 507 // XULListboxAccessible: Widgets
michael@0 508
michael@0 509 bool
michael@0 510 XULListboxAccessible::IsWidget() const
michael@0 511 {
michael@0 512 return true;
michael@0 513 }
michael@0 514
michael@0 515 bool
michael@0 516 XULListboxAccessible::IsActiveWidget() const
michael@0 517 {
michael@0 518 if (IsAutoCompletePopup()) {
michael@0 519 nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
michael@0 520 do_QueryInterface(mContent->GetParent());
michael@0 521
michael@0 522 if (autoCompletePopupElm) {
michael@0 523 bool isOpen = false;
michael@0 524 autoCompletePopupElm->GetPopupOpen(&isOpen);
michael@0 525 return isOpen;
michael@0 526 }
michael@0 527 }
michael@0 528 return FocusMgr()->HasDOMFocus(mContent);
michael@0 529 }
michael@0 530
michael@0 531 bool
michael@0 532 XULListboxAccessible::AreItemsOperable() const
michael@0 533 {
michael@0 534 if (IsAutoCompletePopup()) {
michael@0 535 nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
michael@0 536 do_QueryInterface(mContent->GetParent());
michael@0 537
michael@0 538 if (autoCompletePopupElm) {
michael@0 539 bool isOpen = false;
michael@0 540 autoCompletePopupElm->GetPopupOpen(&isOpen);
michael@0 541 return isOpen;
michael@0 542 }
michael@0 543 }
michael@0 544 return true;
michael@0 545 }
michael@0 546
michael@0 547 Accessible*
michael@0 548 XULListboxAccessible::ContainerWidget() const
michael@0 549 {
michael@0 550 if (IsAutoCompletePopup()) {
michael@0 551 // This works for XUL autocompletes. It doesn't work for HTML forms
michael@0 552 // autocomplete because of potential crossprocess calls (when autocomplete
michael@0 553 // lives in content process while popup lives in chrome process). If that's
michael@0 554 // a problem then rethink Widgets interface.
michael@0 555 nsCOMPtr<nsIDOMXULMenuListElement> menuListElm =
michael@0 556 do_QueryInterface(mContent->GetParent());
michael@0 557 if (menuListElm) {
michael@0 558 nsCOMPtr<nsIDOMNode> inputElm;
michael@0 559 menuListElm->GetInputField(getter_AddRefs(inputElm));
michael@0 560 if (inputElm) {
michael@0 561 nsCOMPtr<nsINode> inputNode = do_QueryInterface(inputElm);
michael@0 562 if (inputNode) {
michael@0 563 Accessible* input =
michael@0 564 mDoc->GetAccessible(inputNode);
michael@0 565 return input ? input->ContainerWidget() : nullptr;
michael@0 566 }
michael@0 567 }
michael@0 568 }
michael@0 569 }
michael@0 570 return nullptr;
michael@0 571 }
michael@0 572
michael@0 573 ////////////////////////////////////////////////////////////////////////////////
michael@0 574 // XULListitemAccessible
michael@0 575 ////////////////////////////////////////////////////////////////////////////////
michael@0 576
michael@0 577 XULListitemAccessible::
michael@0 578 XULListitemAccessible(nsIContent* aContent, DocAccessible* aDoc) :
michael@0 579 XULMenuitemAccessible(aContent, aDoc)
michael@0 580 {
michael@0 581 mIsCheckbox = mContent->AttrValueIs(kNameSpaceID_None,
michael@0 582 nsGkAtoms::type,
michael@0 583 nsGkAtoms::checkbox,
michael@0 584 eCaseMatters);
michael@0 585 mType = eXULListItemType;
michael@0 586 }
michael@0 587
michael@0 588 NS_IMPL_ISUPPORTS_INHERITED0(XULListitemAccessible, Accessible)
michael@0 589
michael@0 590 Accessible*
michael@0 591 XULListitemAccessible::GetListAccessible()
michael@0 592 {
michael@0 593 if (IsDefunct())
michael@0 594 return nullptr;
michael@0 595
michael@0 596 nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem =
michael@0 597 do_QueryInterface(mContent);
michael@0 598 if (!listItem)
michael@0 599 return nullptr;
michael@0 600
michael@0 601 nsCOMPtr<nsIDOMXULSelectControlElement> list;
michael@0 602 listItem->GetControl(getter_AddRefs(list));
michael@0 603
michael@0 604 nsCOMPtr<nsIContent> listContent(do_QueryInterface(list));
michael@0 605 if (!listContent)
michael@0 606 return nullptr;
michael@0 607
michael@0 608 return mDoc->GetAccessible(listContent);
michael@0 609 }
michael@0 610
michael@0 611 ////////////////////////////////////////////////////////////////////////////////
michael@0 612 // XULListitemAccessible Accessible
michael@0 613
michael@0 614 void
michael@0 615 XULListitemAccessible::Description(nsString& aDesc)
michael@0 616 {
michael@0 617 AccessibleWrap::Description(aDesc);
michael@0 618 }
michael@0 619
michael@0 620 ////////////////////////////////////////////////////////////////////////////////
michael@0 621 // XULListitemAccessible. nsIAccessible
michael@0 622
michael@0 623 /**
michael@0 624 * If there is a Listcell as a child ( not anonymous ) use it, otherwise
michael@0 625 * default to getting the name from GetXULName
michael@0 626 */
michael@0 627 ENameValueFlag
michael@0 628 XULListitemAccessible::NativeName(nsString& aName)
michael@0 629 {
michael@0 630 nsIContent* childContent = mContent->GetFirstChild();
michael@0 631 if (childContent) {
michael@0 632 if (childContent->NodeInfo()->Equals(nsGkAtoms::listcell,
michael@0 633 kNameSpaceID_XUL)) {
michael@0 634 childContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
michael@0 635 return eNameOK;
michael@0 636 }
michael@0 637 }
michael@0 638
michael@0 639 return Accessible::NativeName(aName);
michael@0 640 }
michael@0 641
michael@0 642 role
michael@0 643 XULListitemAccessible::NativeRole()
michael@0 644 {
michael@0 645 Accessible* list = GetListAccessible();
michael@0 646 if (!list) {
michael@0 647 NS_ERROR("No list accessible for listitem accessible!");
michael@0 648 return roles::NOTHING;
michael@0 649 }
michael@0 650
michael@0 651 if (list->Role() == roles::TABLE)
michael@0 652 return roles::ROW;
michael@0 653
michael@0 654 if (mIsCheckbox)
michael@0 655 return roles::CHECK_RICH_OPTION;
michael@0 656
michael@0 657 if (mParent && mParent->Role() == roles::COMBOBOX_LIST)
michael@0 658 return roles::COMBOBOX_OPTION;
michael@0 659
michael@0 660 return roles::RICH_OPTION;
michael@0 661 }
michael@0 662
michael@0 663 uint64_t
michael@0 664 XULListitemAccessible::NativeState()
michael@0 665 {
michael@0 666 if (mIsCheckbox)
michael@0 667 return XULMenuitemAccessible::NativeState();
michael@0 668
michael@0 669 uint64_t states = NativeInteractiveState();
michael@0 670
michael@0 671 nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem =
michael@0 672 do_QueryInterface(mContent);
michael@0 673
michael@0 674 if (listItem) {
michael@0 675 bool isSelected;
michael@0 676 listItem->GetSelected(&isSelected);
michael@0 677 if (isSelected)
michael@0 678 states |= states::SELECTED;
michael@0 679
michael@0 680 if (FocusMgr()->IsFocused(this))
michael@0 681 states |= states::FOCUSED;
michael@0 682 }
michael@0 683
michael@0 684 return states;
michael@0 685 }
michael@0 686
michael@0 687 uint64_t
michael@0 688 XULListitemAccessible::NativeInteractiveState() const
michael@0 689 {
michael@0 690 return NativelyUnavailable() || (mParent && mParent->NativelyUnavailable()) ?
michael@0 691 states::UNAVAILABLE : states::FOCUSABLE | states::SELECTABLE;
michael@0 692 }
michael@0 693
michael@0 694 NS_IMETHODIMP
michael@0 695 XULListitemAccessible::GetActionName(uint8_t aIndex, nsAString& aName)
michael@0 696 {
michael@0 697 if (aIndex == eAction_Click && mIsCheckbox) {
michael@0 698 // check or uncheck
michael@0 699 uint64_t states = NativeState();
michael@0 700
michael@0 701 if (states & states::CHECKED)
michael@0 702 aName.AssignLiteral("uncheck");
michael@0 703 else
michael@0 704 aName.AssignLiteral("check");
michael@0 705
michael@0 706 return NS_OK;
michael@0 707 }
michael@0 708 return NS_ERROR_INVALID_ARG;
michael@0 709 }
michael@0 710
michael@0 711 bool
michael@0 712 XULListitemAccessible::CanHaveAnonChildren()
michael@0 713 {
michael@0 714 // That indicates we should walk anonymous children for listitems
michael@0 715 return true;
michael@0 716 }
michael@0 717
michael@0 718 ////////////////////////////////////////////////////////////////////////////////
michael@0 719 // XULListitemAccessible: Widgets
michael@0 720
michael@0 721 Accessible*
michael@0 722 XULListitemAccessible::ContainerWidget() const
michael@0 723 {
michael@0 724 return Parent();
michael@0 725 }
michael@0 726
michael@0 727
michael@0 728 ////////////////////////////////////////////////////////////////////////////////
michael@0 729 // XULListCellAccessible
michael@0 730 ////////////////////////////////////////////////////////////////////////////////
michael@0 731
michael@0 732 XULListCellAccessible::
michael@0 733 XULListCellAccessible(nsIContent* aContent, DocAccessible* aDoc) :
michael@0 734 HyperTextAccessibleWrap(aContent, aDoc), xpcAccessibleTableCell(this)
michael@0 735 {
michael@0 736 mGenericTypes |= eTableCell;
michael@0 737 }
michael@0 738
michael@0 739 ////////////////////////////////////////////////////////////////////////////////
michael@0 740 // nsISupports
michael@0 741
michael@0 742 NS_IMPL_ISUPPORTS_INHERITED(XULListCellAccessible,
michael@0 743 HyperTextAccessible,
michael@0 744 nsIAccessibleTableCell)
michael@0 745
michael@0 746 ////////////////////////////////////////////////////////////////////////////////
michael@0 747 // XULListCellAccessible: nsIAccessibleTableCell implementation
michael@0 748
michael@0 749 TableAccessible*
michael@0 750 XULListCellAccessible::Table() const
michael@0 751 {
michael@0 752 Accessible* thisRow = Parent();
michael@0 753 if (!thisRow || thisRow->Role() != roles::ROW)
michael@0 754 return nullptr;
michael@0 755
michael@0 756 Accessible* table = thisRow->Parent();
michael@0 757 if (!table || table->Role() != roles::TABLE)
michael@0 758 return nullptr;
michael@0 759
michael@0 760 return table->AsTable();
michael@0 761 }
michael@0 762
michael@0 763 uint32_t
michael@0 764 XULListCellAccessible::ColIdx() const
michael@0 765 {
michael@0 766 Accessible* row = Parent();
michael@0 767 if (!row)
michael@0 768 return 0;
michael@0 769
michael@0 770 int32_t indexInRow = IndexInParent();
michael@0 771 uint32_t colIdx = 0;
michael@0 772 for (int32_t idx = 0; idx < indexInRow; idx++) {
michael@0 773 Accessible* cell = row->GetChildAt(idx);
michael@0 774 roles::Role role = cell->Role();
michael@0 775 if (role == roles::CELL || role == roles::GRID_CELL ||
michael@0 776 role == roles::ROWHEADER || role == roles::COLUMNHEADER)
michael@0 777 colIdx++;
michael@0 778 }
michael@0 779
michael@0 780 return colIdx;
michael@0 781 }
michael@0 782
michael@0 783 uint32_t
michael@0 784 XULListCellAccessible::RowIdx() const
michael@0 785 {
michael@0 786 Accessible* row = Parent();
michael@0 787 if (!row)
michael@0 788 return 0;
michael@0 789
michael@0 790 Accessible* table = row->Parent();
michael@0 791 if (!table)
michael@0 792 return 0;
michael@0 793
michael@0 794 int32_t indexInTable = row->IndexInParent();
michael@0 795 uint32_t rowIdx = 0;
michael@0 796 for (int32_t idx = 0; idx < indexInTable; idx++) {
michael@0 797 row = table->GetChildAt(idx);
michael@0 798 if (row->Role() == roles::ROW)
michael@0 799 rowIdx++;
michael@0 800 }
michael@0 801
michael@0 802 return rowIdx;
michael@0 803 }
michael@0 804
michael@0 805 void
michael@0 806 XULListCellAccessible::ColHeaderCells(nsTArray<Accessible*>* aCells)
michael@0 807 {
michael@0 808 TableAccessible* table = Table();
michael@0 809 NS_ASSERTION(table, "cell not in a table!");
michael@0 810 if (!table)
michael@0 811 return;
michael@0 812
michael@0 813 // Get column header cell from XUL listhead.
michael@0 814 Accessible* list = nullptr;
michael@0 815
michael@0 816 Accessible* tableAcc = table->AsAccessible();
michael@0 817 uint32_t tableChildCount = tableAcc->ChildCount();
michael@0 818 for (uint32_t childIdx = 0; childIdx < tableChildCount; childIdx++) {
michael@0 819 Accessible* child = tableAcc->GetChildAt(childIdx);
michael@0 820 if (child->Role() == roles::LIST) {
michael@0 821 list = child;
michael@0 822 break;
michael@0 823 }
michael@0 824 }
michael@0 825
michael@0 826 if (list) {
michael@0 827 Accessible* headerCell = list->GetChildAt(ColIdx());
michael@0 828 if (headerCell) {
michael@0 829 aCells->AppendElement(headerCell);
michael@0 830 return;
michael@0 831 }
michael@0 832 }
michael@0 833
michael@0 834 // No column header cell from XUL markup, try to get it from ARIA markup.
michael@0 835 TableCellAccessible::ColHeaderCells(aCells);
michael@0 836 }
michael@0 837
michael@0 838 bool
michael@0 839 XULListCellAccessible::Selected()
michael@0 840 {
michael@0 841 TableAccessible* table = Table();
michael@0 842 NS_ENSURE_TRUE(table, false); // we expect to be in a listbox (table)
michael@0 843
michael@0 844 return table->IsRowSelected(RowIdx());
michael@0 845 }
michael@0 846
michael@0 847 ////////////////////////////////////////////////////////////////////////////////
michael@0 848 // XULListCellAccessible. Accessible implementation
michael@0 849
michael@0 850 void
michael@0 851 XULListCellAccessible::Shutdown()
michael@0 852 {
michael@0 853 mTableCell = nullptr;
michael@0 854 HyperTextAccessibleWrap::Shutdown();
michael@0 855 }
michael@0 856
michael@0 857 role
michael@0 858 XULListCellAccessible::NativeRole()
michael@0 859 {
michael@0 860 return roles::CELL;
michael@0 861 }
michael@0 862
michael@0 863 already_AddRefed<nsIPersistentProperties>
michael@0 864 XULListCellAccessible::NativeAttributes()
michael@0 865 {
michael@0 866 nsCOMPtr<nsIPersistentProperties> attributes =
michael@0 867 HyperTextAccessibleWrap::NativeAttributes();
michael@0 868
michael@0 869 // "table-cell-index" attribute
michael@0 870 TableAccessible* table = Table();
michael@0 871 if (!table) // we expect to be in a listbox (table)
michael@0 872 return attributes.forget();
michael@0 873
michael@0 874 nsAutoString stringIdx;
michael@0 875 stringIdx.AppendInt(table->CellIndexAt(RowIdx(), ColIdx()));
michael@0 876 nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx);
michael@0 877
michael@0 878 return attributes.forget();
michael@0 879 }

mercurial