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