accessible/src/xul/XULMenuAccessible.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; 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 "XULMenuAccessible.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 #include "XULFormControlAccessible.h"
michael@0 15
michael@0 16 #include "nsIDOMElement.h"
michael@0 17 #include "nsIDOMXULElement.h"
michael@0 18 #include "nsIMutableArray.h"
michael@0 19 #include "nsIDOMXULContainerElement.h"
michael@0 20 #include "nsIDOMXULSelectCntrlItemEl.h"
michael@0 21 #include "nsIDOMXULMultSelectCntrlEl.h"
michael@0 22 #include "nsIDOMKeyEvent.h"
michael@0 23 #include "nsIServiceManager.h"
michael@0 24 #include "nsIPresShell.h"
michael@0 25 #include "nsIContent.h"
michael@0 26 #include "nsMenuBarFrame.h"
michael@0 27 #include "nsMenuPopupFrame.h"
michael@0 28
michael@0 29 #include "mozilla/Preferences.h"
michael@0 30 #include "mozilla/LookAndFeel.h"
michael@0 31 #include "mozilla/dom/Element.h"
michael@0 32
michael@0 33 using namespace mozilla;
michael@0 34 using namespace mozilla::a11y;
michael@0 35
michael@0 36 ////////////////////////////////////////////////////////////////////////////////
michael@0 37 // XULMenuitemAccessible
michael@0 38 ////////////////////////////////////////////////////////////////////////////////
michael@0 39
michael@0 40 XULMenuitemAccessible::
michael@0 41 XULMenuitemAccessible(nsIContent* aContent, DocAccessible* aDoc) :
michael@0 42 AccessibleWrap(aContent, aDoc)
michael@0 43 {
michael@0 44 }
michael@0 45
michael@0 46 uint64_t
michael@0 47 XULMenuitemAccessible::NativeState()
michael@0 48 {
michael@0 49 uint64_t state = Accessible::NativeState();
michael@0 50
michael@0 51 // Has Popup?
michael@0 52 if (mContent->NodeInfo()->Equals(nsGkAtoms::menu, kNameSpaceID_XUL)) {
michael@0 53 state |= states::HASPOPUP;
michael@0 54 if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::open))
michael@0 55 state |= states::EXPANDED;
michael@0 56 else
michael@0 57 state |= states::COLLAPSED;
michael@0 58 }
michael@0 59
michael@0 60 // Checkable/checked?
michael@0 61 static nsIContent::AttrValuesArray strings[] =
michael@0 62 { &nsGkAtoms::radio, &nsGkAtoms::checkbox, nullptr };
michael@0 63
michael@0 64 if (mContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::type, strings,
michael@0 65 eCaseMatters) >= 0) {
michael@0 66
michael@0 67 // Checkable?
michael@0 68 state |= states::CHECKABLE;
michael@0 69
michael@0 70 // Checked?
michael@0 71 if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::checked,
michael@0 72 nsGkAtoms::_true, eCaseMatters))
michael@0 73 state |= states::CHECKED;
michael@0 74 }
michael@0 75
michael@0 76 // Combo box listitem
michael@0 77 bool isComboboxOption = (Role() == roles::COMBOBOX_OPTION);
michael@0 78 if (isComboboxOption) {
michael@0 79 // Is selected?
michael@0 80 bool isSelected = false;
michael@0 81 nsCOMPtr<nsIDOMXULSelectControlItemElement>
michael@0 82 item(do_QueryInterface(mContent));
michael@0 83 NS_ENSURE_TRUE(item, state);
michael@0 84 item->GetSelected(&isSelected);
michael@0 85
michael@0 86 // Is collapsed?
michael@0 87 bool isCollapsed = false;
michael@0 88 Accessible* parent = Parent();
michael@0 89 if (parent && parent->State() & states::INVISIBLE)
michael@0 90 isCollapsed = true;
michael@0 91
michael@0 92 if (isSelected) {
michael@0 93 state |= states::SELECTED;
michael@0 94
michael@0 95 // Selected and collapsed?
michael@0 96 if (isCollapsed) {
michael@0 97 // Set selected option offscreen/invisible according to combobox state
michael@0 98 Accessible* grandParent = parent->Parent();
michael@0 99 if (!grandParent)
michael@0 100 return state;
michael@0 101 NS_ASSERTION(grandParent->Role() == roles::COMBOBOX,
michael@0 102 "grandparent of combobox listitem is not combobox");
michael@0 103 uint64_t grandParentState = grandParent->State();
michael@0 104 state &= ~(states::OFFSCREEN | states::INVISIBLE);
michael@0 105 state |= (grandParentState & states::OFFSCREEN) |
michael@0 106 (grandParentState & states::INVISIBLE) |
michael@0 107 (grandParentState & states::OPAQUE1);
michael@0 108 } // isCollapsed
michael@0 109 } // isSelected
michael@0 110 } // ROLE_COMBOBOX_OPTION
michael@0 111
michael@0 112 return state;
michael@0 113 }
michael@0 114
michael@0 115 uint64_t
michael@0 116 XULMenuitemAccessible::NativeInteractiveState() const
michael@0 117 {
michael@0 118 if (NativelyUnavailable()) {
michael@0 119 // Note: keep in sinc with nsXULPopupManager::IsValidMenuItem() logic.
michael@0 120 bool skipNavigatingDisabledMenuItem = true;
michael@0 121 nsMenuFrame* menuFrame = do_QueryFrame(GetFrame());
michael@0 122 if (!menuFrame || !menuFrame->IsOnMenuBar()) {
michael@0 123 skipNavigatingDisabledMenuItem = LookAndFeel::
michael@0 124 GetInt(LookAndFeel::eIntID_SkipNavigatingDisabledMenuItem, 0) != 0;
michael@0 125 }
michael@0 126
michael@0 127 if (skipNavigatingDisabledMenuItem)
michael@0 128 return states::UNAVAILABLE;
michael@0 129
michael@0 130 return states::UNAVAILABLE | states::FOCUSABLE | states::SELECTABLE;
michael@0 131 }
michael@0 132
michael@0 133 return states::FOCUSABLE | states::SELECTABLE;
michael@0 134 }
michael@0 135
michael@0 136 ENameValueFlag
michael@0 137 XULMenuitemAccessible::NativeName(nsString& aName)
michael@0 138 {
michael@0 139 mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
michael@0 140 return eNameOK;
michael@0 141 }
michael@0 142
michael@0 143 void
michael@0 144 XULMenuitemAccessible::Description(nsString& aDescription)
michael@0 145 {
michael@0 146 mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::description,
michael@0 147 aDescription);
michael@0 148 }
michael@0 149
michael@0 150 KeyBinding
michael@0 151 XULMenuitemAccessible::AccessKey() const
michael@0 152 {
michael@0 153 // Return menu accesskey: N or Alt+F.
michael@0 154 static int32_t gMenuAccesskeyModifier = -1; // magic value of -1 indicates unitialized state
michael@0 155
michael@0 156 // We do not use nsCoreUtils::GetAccesskeyFor() because accesskeys for
michael@0 157 // menu are't registered by EventStateManager.
michael@0 158 nsAutoString accesskey;
michael@0 159 mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey,
michael@0 160 accesskey);
michael@0 161 if (accesskey.IsEmpty())
michael@0 162 return KeyBinding();
michael@0 163
michael@0 164 uint32_t modifierKey = 0;
michael@0 165
michael@0 166 Accessible* parentAcc = Parent();
michael@0 167 if (parentAcc) {
michael@0 168 if (parentAcc->NativeRole() == roles::MENUBAR) {
michael@0 169 // If top level menu item, add Alt+ or whatever modifier text to string
michael@0 170 // No need to cache pref service, this happens rarely
michael@0 171 if (gMenuAccesskeyModifier == -1) {
michael@0 172 // Need to initialize cached global accesskey pref
michael@0 173 gMenuAccesskeyModifier = Preferences::GetInt("ui.key.menuAccessKey", 0);
michael@0 174 }
michael@0 175
michael@0 176 switch (gMenuAccesskeyModifier) {
michael@0 177 case nsIDOMKeyEvent::DOM_VK_CONTROL:
michael@0 178 modifierKey = KeyBinding::kControl;
michael@0 179 break;
michael@0 180 case nsIDOMKeyEvent::DOM_VK_ALT:
michael@0 181 modifierKey = KeyBinding::kAlt;
michael@0 182 break;
michael@0 183 case nsIDOMKeyEvent::DOM_VK_META:
michael@0 184 modifierKey = KeyBinding::kMeta;
michael@0 185 break;
michael@0 186 case nsIDOMKeyEvent::DOM_VK_WIN:
michael@0 187 modifierKey = KeyBinding::kOS;
michael@0 188 break;
michael@0 189 }
michael@0 190 }
michael@0 191 }
michael@0 192
michael@0 193 return KeyBinding(accesskey[0], modifierKey);
michael@0 194 }
michael@0 195
michael@0 196 KeyBinding
michael@0 197 XULMenuitemAccessible::KeyboardShortcut() const
michael@0 198 {
michael@0 199 nsAutoString keyElmId;
michael@0 200 mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::key, keyElmId);
michael@0 201 if (keyElmId.IsEmpty())
michael@0 202 return KeyBinding();
michael@0 203
michael@0 204 nsIContent* keyElm = mContent->OwnerDoc()->GetElementById(keyElmId);
michael@0 205 if (!keyElm)
michael@0 206 return KeyBinding();
michael@0 207
michael@0 208 uint32_t key = 0;
michael@0 209
michael@0 210 nsAutoString keyStr;
michael@0 211 keyElm->GetAttr(kNameSpaceID_None, nsGkAtoms::key, keyStr);
michael@0 212 if (keyStr.IsEmpty()) {
michael@0 213 nsAutoString keyCodeStr;
michael@0 214 keyElm->GetAttr(kNameSpaceID_None, nsGkAtoms::keycode, keyCodeStr);
michael@0 215 nsresult errorCode;
michael@0 216 key = keyStr.ToInteger(&errorCode, kAutoDetect);
michael@0 217 } else {
michael@0 218 key = keyStr[0];
michael@0 219 }
michael@0 220
michael@0 221 nsAutoString modifiersStr;
michael@0 222 keyElm->GetAttr(kNameSpaceID_None, nsGkAtoms::modifiers, modifiersStr);
michael@0 223
michael@0 224 uint32_t modifierMask = 0;
michael@0 225 if (modifiersStr.Find("shift") != -1)
michael@0 226 modifierMask |= KeyBinding::kShift;
michael@0 227 if (modifiersStr.Find("alt") != -1)
michael@0 228 modifierMask |= KeyBinding::kAlt;
michael@0 229 if (modifiersStr.Find("meta") != -1)
michael@0 230 modifierMask |= KeyBinding::kMeta;
michael@0 231 if (modifiersStr.Find("os") != -1)
michael@0 232 modifierMask |= KeyBinding::kOS;
michael@0 233 if (modifiersStr.Find("control") != -1)
michael@0 234 modifierMask |= KeyBinding::kControl;
michael@0 235 if (modifiersStr.Find("accel") != -1) {
michael@0 236 // Get the accelerator key value from prefs, overriding the default.
michael@0 237 switch (Preferences::GetInt("ui.key.accelKey", 0)) {
michael@0 238 case nsIDOMKeyEvent::DOM_VK_META:
michael@0 239 modifierMask |= KeyBinding::kMeta;
michael@0 240 break;
michael@0 241
michael@0 242 case nsIDOMKeyEvent::DOM_VK_WIN:
michael@0 243 modifierMask |= KeyBinding::kOS;
michael@0 244 break;
michael@0 245
michael@0 246 case nsIDOMKeyEvent::DOM_VK_ALT:
michael@0 247 modifierMask |= KeyBinding::kAlt;
michael@0 248 break;
michael@0 249
michael@0 250 case nsIDOMKeyEvent::DOM_VK_CONTROL:
michael@0 251 modifierMask |= KeyBinding::kControl;
michael@0 252 break;
michael@0 253
michael@0 254 default:
michael@0 255 #ifdef XP_MACOSX
michael@0 256 modifierMask |= KeyBinding::kMeta;
michael@0 257 #else
michael@0 258 modifierMask |= KeyBinding::kControl;
michael@0 259 #endif
michael@0 260 }
michael@0 261 }
michael@0 262
michael@0 263 return KeyBinding(key, modifierMask);
michael@0 264 }
michael@0 265
michael@0 266 role
michael@0 267 XULMenuitemAccessible::NativeRole()
michael@0 268 {
michael@0 269 nsCOMPtr<nsIDOMXULContainerElement> xulContainer(do_QueryInterface(mContent));
michael@0 270 if (xulContainer)
michael@0 271 return roles::PARENT_MENUITEM;
michael@0 272
michael@0 273 if (mParent && mParent->Role() == roles::COMBOBOX_LIST)
michael@0 274 return roles::COMBOBOX_OPTION;
michael@0 275
michael@0 276 if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
michael@0 277 nsGkAtoms::radio, eCaseMatters))
michael@0 278 return roles::RADIO_MENU_ITEM;
michael@0 279
michael@0 280 if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
michael@0 281 nsGkAtoms::checkbox,
michael@0 282 eCaseMatters))
michael@0 283 return roles::CHECK_MENU_ITEM;
michael@0 284
michael@0 285 return roles::MENUITEM;
michael@0 286 }
michael@0 287
michael@0 288 int32_t
michael@0 289 XULMenuitemAccessible::GetLevelInternal()
michael@0 290 {
michael@0 291 return nsAccUtils::GetLevelForXULContainerItem(mContent);
michael@0 292 }
michael@0 293
michael@0 294 bool
michael@0 295 XULMenuitemAccessible::CanHaveAnonChildren()
michael@0 296 {
michael@0 297 // That indicates we don't walk anonymous children for menuitems
michael@0 298 return false;
michael@0 299 }
michael@0 300
michael@0 301 NS_IMETHODIMP
michael@0 302 XULMenuitemAccessible::DoAction(uint8_t index)
michael@0 303 {
michael@0 304 if (index == eAction_Click) { // default action
michael@0 305 DoCommand();
michael@0 306 return NS_OK;
michael@0 307 }
michael@0 308
michael@0 309 return NS_ERROR_INVALID_ARG;
michael@0 310 }
michael@0 311
michael@0 312 /** select us! close combo box if necessary*/
michael@0 313 NS_IMETHODIMP
michael@0 314 XULMenuitemAccessible::GetActionName(uint8_t aIndex, nsAString& aName)
michael@0 315 {
michael@0 316 if (aIndex == eAction_Click) {
michael@0 317 aName.AssignLiteral("click");
michael@0 318 return NS_OK;
michael@0 319 }
michael@0 320 return NS_ERROR_INVALID_ARG;
michael@0 321 }
michael@0 322
michael@0 323 uint8_t
michael@0 324 XULMenuitemAccessible::ActionCount()
michael@0 325 {
michael@0 326 return 1;
michael@0 327 }
michael@0 328
michael@0 329 ////////////////////////////////////////////////////////////////////////////////
michael@0 330 // XULMenuitemAccessible: Widgets
michael@0 331
michael@0 332 bool
michael@0 333 XULMenuitemAccessible::IsActiveWidget() const
michael@0 334 {
michael@0 335 // Parent menu item is a widget, it's active when its popup is open.
michael@0 336 nsIContent* menuPopupContent = mContent->GetFirstChild();
michael@0 337 if (menuPopupContent) {
michael@0 338 nsMenuPopupFrame* menuPopupFrame =
michael@0 339 do_QueryFrame(menuPopupContent->GetPrimaryFrame());
michael@0 340 return menuPopupFrame && menuPopupFrame->IsOpen();
michael@0 341 }
michael@0 342 return false;
michael@0 343 }
michael@0 344
michael@0 345 bool
michael@0 346 XULMenuitemAccessible::AreItemsOperable() const
michael@0 347 {
michael@0 348 // Parent menu item is a widget, its items are operable when its popup is open.
michael@0 349 nsIContent* menuPopupContent = mContent->GetFirstChild();
michael@0 350 if (menuPopupContent) {
michael@0 351 nsMenuPopupFrame* menuPopupFrame =
michael@0 352 do_QueryFrame(menuPopupContent->GetPrimaryFrame());
michael@0 353 return menuPopupFrame && menuPopupFrame->IsOpen();
michael@0 354 }
michael@0 355 return false;
michael@0 356 }
michael@0 357
michael@0 358 Accessible*
michael@0 359 XULMenuitemAccessible::ContainerWidget() const
michael@0 360 {
michael@0 361 nsMenuFrame* menuFrame = do_QueryFrame(GetFrame());
michael@0 362 if (menuFrame) {
michael@0 363 nsMenuParent* menuParent = menuFrame->GetMenuParent();
michael@0 364 if (menuParent) {
michael@0 365 if (menuParent->IsMenuBar()) // menubar menu
michael@0 366 return mParent;
michael@0 367
michael@0 368 // a menupoup or parent menu item
michael@0 369 if (menuParent->IsMenu())
michael@0 370 return mParent;
michael@0 371
michael@0 372 // otherwise it's different kind of popups (like panel or tooltip), it
michael@0 373 // shouldn't be a real case.
michael@0 374 }
michael@0 375 }
michael@0 376 return nullptr;
michael@0 377 }
michael@0 378
michael@0 379
michael@0 380 ////////////////////////////////////////////////////////////////////////////////
michael@0 381 // XULMenuSeparatorAccessible
michael@0 382 ////////////////////////////////////////////////////////////////////////////////
michael@0 383
michael@0 384 XULMenuSeparatorAccessible::
michael@0 385 XULMenuSeparatorAccessible(nsIContent* aContent, DocAccessible* aDoc) :
michael@0 386 XULMenuitemAccessible(aContent, aDoc)
michael@0 387 {
michael@0 388 }
michael@0 389
michael@0 390 uint64_t
michael@0 391 XULMenuSeparatorAccessible::NativeState()
michael@0 392 {
michael@0 393 // Isn't focusable, but can be offscreen/invisible -- only copy those states
michael@0 394 return XULMenuitemAccessible::NativeState() &
michael@0 395 (states::OFFSCREEN | states::INVISIBLE);
michael@0 396 }
michael@0 397
michael@0 398 ENameValueFlag
michael@0 399 XULMenuSeparatorAccessible::NativeName(nsString& aName)
michael@0 400 {
michael@0 401 return eNameOK;
michael@0 402 }
michael@0 403
michael@0 404 role
michael@0 405 XULMenuSeparatorAccessible::NativeRole()
michael@0 406 {
michael@0 407 return roles::SEPARATOR;
michael@0 408 }
michael@0 409
michael@0 410 NS_IMETHODIMP
michael@0 411 XULMenuSeparatorAccessible::DoAction(uint8_t index)
michael@0 412 {
michael@0 413 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 414 }
michael@0 415
michael@0 416 NS_IMETHODIMP
michael@0 417 XULMenuSeparatorAccessible::GetActionName(uint8_t aIndex, nsAString& aName)
michael@0 418 {
michael@0 419 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 420 }
michael@0 421
michael@0 422 uint8_t
michael@0 423 XULMenuSeparatorAccessible::ActionCount()
michael@0 424 {
michael@0 425 return 0;
michael@0 426 }
michael@0 427
michael@0 428 ////////////////////////////////////////////////////////////////////////////////
michael@0 429 // XULMenupopupAccessible
michael@0 430 ////////////////////////////////////////////////////////////////////////////////
michael@0 431
michael@0 432 XULMenupopupAccessible::
michael@0 433 XULMenupopupAccessible(nsIContent* aContent, DocAccessible* aDoc) :
michael@0 434 XULSelectControlAccessible(aContent, aDoc)
michael@0 435 {
michael@0 436 nsMenuPopupFrame* menuPopupFrame = do_QueryFrame(GetFrame());
michael@0 437 if (menuPopupFrame && menuPopupFrame->IsMenu())
michael@0 438 mType = eMenuPopupType;
michael@0 439
michael@0 440 // May be the anonymous <menupopup> inside <menulist> (a combobox)
michael@0 441 mSelectControl = do_QueryInterface(mContent->GetFlattenedTreeParent());
michael@0 442 if (!mSelectControl)
michael@0 443 mGenericTypes &= ~eSelect;
michael@0 444 }
michael@0 445
michael@0 446 uint64_t
michael@0 447 XULMenupopupAccessible::NativeState()
michael@0 448 {
michael@0 449 uint64_t state = Accessible::NativeState();
michael@0 450
michael@0 451 #ifdef DEBUG
michael@0 452 // We are onscreen if our parent is active
michael@0 453 bool isActive = mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::menuactive);
michael@0 454 if (!isActive) {
michael@0 455 Accessible* parent = Parent();
michael@0 456 if (parent) {
michael@0 457 nsIContent* parentContent = parent->GetContent();
michael@0 458 if (parentContent)
michael@0 459 isActive = parentContent->HasAttr(kNameSpaceID_None, nsGkAtoms::open);
michael@0 460 }
michael@0 461 }
michael@0 462
michael@0 463 NS_ASSERTION(isActive || (state & states::INVISIBLE),
michael@0 464 "XULMenupopup doesn't have INVISIBLE when it's inactive");
michael@0 465 #endif
michael@0 466
michael@0 467 if (state & states::INVISIBLE)
michael@0 468 state |= states::OFFSCREEN | states::COLLAPSED;
michael@0 469
michael@0 470 return state;
michael@0 471 }
michael@0 472
michael@0 473 ENameValueFlag
michael@0 474 XULMenupopupAccessible::NativeName(nsString& aName)
michael@0 475 {
michael@0 476 nsIContent* content = mContent;
michael@0 477 while (content && aName.IsEmpty()) {
michael@0 478 content->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
michael@0 479 content = content->GetFlattenedTreeParent();
michael@0 480 }
michael@0 481
michael@0 482 return eNameOK;
michael@0 483 }
michael@0 484
michael@0 485 role
michael@0 486 XULMenupopupAccessible::NativeRole()
michael@0 487 {
michael@0 488 // If accessible is not bound to the tree (this happens while children are
michael@0 489 // cached) return general role.
michael@0 490 if (mParent) {
michael@0 491 roles::Role role = mParent->Role();
michael@0 492 if (role == roles::COMBOBOX || role == roles::AUTOCOMPLETE)
michael@0 493 return roles::COMBOBOX_LIST;
michael@0 494
michael@0 495 if (role == roles::PUSHBUTTON) {
michael@0 496 // Some widgets like the search bar have several popups, owned by buttons.
michael@0 497 Accessible* grandParent = mParent->Parent();
michael@0 498 if (grandParent && grandParent->Role() == roles::AUTOCOMPLETE)
michael@0 499 return roles::COMBOBOX_LIST;
michael@0 500 }
michael@0 501 }
michael@0 502
michael@0 503 return roles::MENUPOPUP;
michael@0 504 }
michael@0 505
michael@0 506 ////////////////////////////////////////////////////////////////////////////////
michael@0 507 // XULMenupopupAccessible: Widgets
michael@0 508
michael@0 509 bool
michael@0 510 XULMenupopupAccessible::IsWidget() const
michael@0 511 {
michael@0 512 return true;
michael@0 513 }
michael@0 514
michael@0 515 bool
michael@0 516 XULMenupopupAccessible::IsActiveWidget() const
michael@0 517 {
michael@0 518 // If menupopup is a widget (the case of context menus) then active when open.
michael@0 519 nsMenuPopupFrame* menuPopupFrame = do_QueryFrame(GetFrame());
michael@0 520 return menuPopupFrame && menuPopupFrame->IsOpen();
michael@0 521 }
michael@0 522
michael@0 523 bool
michael@0 524 XULMenupopupAccessible::AreItemsOperable() const
michael@0 525 {
michael@0 526 nsMenuPopupFrame* menuPopupFrame = do_QueryFrame(GetFrame());
michael@0 527 return menuPopupFrame && menuPopupFrame->IsOpen();
michael@0 528 }
michael@0 529
michael@0 530 Accessible*
michael@0 531 XULMenupopupAccessible::ContainerWidget() const
michael@0 532 {
michael@0 533 DocAccessible* document = Document();
michael@0 534
michael@0 535 nsMenuPopupFrame* menuPopupFrame = do_QueryFrame(GetFrame());
michael@0 536 while (menuPopupFrame) {
michael@0 537 Accessible* menuPopup =
michael@0 538 document->GetAccessible(menuPopupFrame->GetContent());
michael@0 539 if (!menuPopup) // shouldn't be a real case
michael@0 540 return nullptr;
michael@0 541
michael@0 542 nsMenuFrame* menuFrame = do_QueryFrame(menuPopupFrame->GetParent());
michael@0 543 if (!menuFrame) // context menu or popups
michael@0 544 return nullptr;
michael@0 545
michael@0 546 nsMenuParent* menuParent = menuFrame->GetMenuParent();
michael@0 547 if (!menuParent) // menulist or menubutton
michael@0 548 return menuPopup->Parent();
michael@0 549
michael@0 550 if (menuParent->IsMenuBar()) { // menubar menu
michael@0 551 nsMenuBarFrame* menuBarFrame = static_cast<nsMenuBarFrame*>(menuParent);
michael@0 552 return document->GetAccessible(menuBarFrame->GetContent());
michael@0 553 }
michael@0 554
michael@0 555 // different kind of popups like panel or tooltip
michael@0 556 if (!menuParent->IsMenu())
michael@0 557 return nullptr;
michael@0 558
michael@0 559 menuPopupFrame = static_cast<nsMenuPopupFrame*>(menuParent);
michael@0 560 }
michael@0 561
michael@0 562 NS_NOTREACHED("Shouldn't be a real case.");
michael@0 563 return nullptr;
michael@0 564 }
michael@0 565
michael@0 566 ////////////////////////////////////////////////////////////////////////////////
michael@0 567 // XULMenubarAccessible
michael@0 568 ////////////////////////////////////////////////////////////////////////////////
michael@0 569
michael@0 570 XULMenubarAccessible::
michael@0 571 XULMenubarAccessible(nsIContent* aContent, DocAccessible* aDoc) :
michael@0 572 AccessibleWrap(aContent, aDoc)
michael@0 573 {
michael@0 574 }
michael@0 575
michael@0 576 ENameValueFlag
michael@0 577 XULMenubarAccessible::NativeName(nsString& aName)
michael@0 578 {
michael@0 579 aName.AssignLiteral("Application");
michael@0 580 return eNameOK;
michael@0 581 }
michael@0 582
michael@0 583 role
michael@0 584 XULMenubarAccessible::NativeRole()
michael@0 585 {
michael@0 586 return roles::MENUBAR;
michael@0 587 }
michael@0 588
michael@0 589 ////////////////////////////////////////////////////////////////////////////////
michael@0 590 // XULMenubarAccessible: Widgets
michael@0 591
michael@0 592 bool
michael@0 593 XULMenubarAccessible::IsActiveWidget() const
michael@0 594 {
michael@0 595 nsMenuBarFrame* menuBarFrame = do_QueryFrame(GetFrame());
michael@0 596 return menuBarFrame && menuBarFrame->IsActive();
michael@0 597 }
michael@0 598
michael@0 599 bool
michael@0 600 XULMenubarAccessible::AreItemsOperable() const
michael@0 601 {
michael@0 602 return true;
michael@0 603 }
michael@0 604
michael@0 605 Accessible*
michael@0 606 XULMenubarAccessible::CurrentItem()
michael@0 607 {
michael@0 608 nsMenuBarFrame* menuBarFrame = do_QueryFrame(GetFrame());
michael@0 609 if (menuBarFrame) {
michael@0 610 nsMenuFrame* menuFrame = menuBarFrame->GetCurrentMenuItem();
michael@0 611 if (menuFrame) {
michael@0 612 nsIContent* menuItemNode = menuFrame->GetContent();
michael@0 613 return mDoc->GetAccessible(menuItemNode);
michael@0 614 }
michael@0 615 }
michael@0 616 return nullptr;
michael@0 617 }
michael@0 618
michael@0 619 void
michael@0 620 XULMenubarAccessible::SetCurrentItem(Accessible* aItem)
michael@0 621 {
michael@0 622 NS_ERROR("XULMenubarAccessible::SetCurrentItem not implemented");
michael@0 623 }

mercurial