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