HTMLImageMapAccessible.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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. #include "HTMLImageMapAccessible.h"
  6. #include "ARIAMap.h"
  7. #include "nsAccUtils.h"
  8. #include "DocAccessible-inl.h"
  9. #include "Role.h"
  10. #include "nsIDOMHTMLCollection.h"
  11. #include "nsIServiceManager.h"
  12. #include "nsIDOMElement.h"
  13. #include "nsIDOMHTMLAreaElement.h"
  14. #include "nsIFrame.h"
  15. #include "nsImageFrame.h"
  16. #include "nsImageMap.h"
  17. #include "nsIURI.h"
  18. using namespace mozilla::a11y;
  19. ////////////////////////////////////////////////////////////////////////////////
  20. // HTMLImageMapAccessible
  21. ////////////////////////////////////////////////////////////////////////////////
  22. HTMLImageMapAccessible::
  23. HTMLImageMapAccessible(nsIContent* aContent, DocAccessible* aDoc) :
  24. ImageAccessibleWrap(aContent, aDoc)
  25. {
  26. mType = eImageMapType;
  27. UpdateChildAreas(false);
  28. }
  29. ////////////////////////////////////////////////////////////////////////////////
  30. // HTMLImageMapAccessible: nsISupports
  31. NS_IMPL_ISUPPORTS_INHERITED0(HTMLImageMapAccessible, ImageAccessible)
  32. ////////////////////////////////////////////////////////////////////////////////
  33. // HTMLImageMapAccessible: Accessible public
  34. role
  35. HTMLImageMapAccessible::NativeRole()
  36. {
  37. return roles::IMAGE_MAP;
  38. }
  39. ////////////////////////////////////////////////////////////////////////////////
  40. // HTMLImageMapAccessible: HyperLinkAccessible
  41. uint32_t
  42. HTMLImageMapAccessible::AnchorCount()
  43. {
  44. return ChildCount();
  45. }
  46. Accessible*
  47. HTMLImageMapAccessible::AnchorAt(uint32_t aAnchorIndex)
  48. {
  49. return GetChildAt(aAnchorIndex);
  50. }
  51. already_AddRefed<nsIURI>
  52. HTMLImageMapAccessible::AnchorURIAt(uint32_t aAnchorIndex)
  53. {
  54. Accessible* area = GetChildAt(aAnchorIndex);
  55. if (!area)
  56. return nullptr;
  57. nsIContent* linkContent = area->GetContent();
  58. return linkContent ? linkContent->GetHrefURI() : nullptr;
  59. }
  60. ////////////////////////////////////////////////////////////////////////////////
  61. // HTMLImageMapAccessible: public
  62. void
  63. HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
  64. {
  65. nsImageFrame* imageFrame = do_QueryFrame(mContent->GetPrimaryFrame());
  66. // If image map is not initialized yet then we trigger one time more later.
  67. nsImageMap* imageMapObj = imageFrame->GetExistingImageMap();
  68. if (!imageMapObj)
  69. return;
  70. TreeMutation mt(this, TreeMutation::kNoEvents & !aDoFireEvents);
  71. // Remove areas that are not a valid part of the image map anymore.
  72. for (int32_t childIdx = mChildren.Length() - 1; childIdx >= 0; childIdx--) {
  73. Accessible* area = mChildren.ElementAt(childIdx);
  74. if (area->GetContent()->GetPrimaryFrame())
  75. continue;
  76. mt.BeforeRemoval(area);
  77. RemoveChild(area);
  78. }
  79. // Insert new areas into the tree.
  80. uint32_t areaElmCount = imageMapObj->AreaCount();
  81. for (uint32_t idx = 0; idx < areaElmCount; idx++) {
  82. nsIContent* areaContent = imageMapObj->GetAreaAt(idx);
  83. Accessible* area = mChildren.SafeElementAt(idx);
  84. if (!area || area->GetContent() != areaContent) {
  85. RefPtr<Accessible> area = new HTMLAreaAccessible(areaContent, mDoc);
  86. mDoc->BindToDocument(area, aria::GetRoleMap(areaContent->AsElement()));
  87. if (!InsertChildAt(idx, area)) {
  88. mDoc->UnbindFromDocument(area);
  89. break;
  90. }
  91. mt.AfterInsertion(area);
  92. }
  93. }
  94. mt.Done();
  95. }
  96. Accessible*
  97. HTMLImageMapAccessible::GetChildAccessibleFor(const nsINode* aNode) const
  98. {
  99. uint32_t length = mChildren.Length();
  100. for (uint32_t i = 0; i < length; i++) {
  101. Accessible* area = mChildren[i];
  102. if (area->GetContent() == aNode)
  103. return area;
  104. }
  105. return nullptr;
  106. }
  107. ////////////////////////////////////////////////////////////////////////////////
  108. // HTMLAreaAccessible
  109. ////////////////////////////////////////////////////////////////////////////////
  110. HTMLAreaAccessible::
  111. HTMLAreaAccessible(nsIContent* aContent, DocAccessible* aDoc) :
  112. HTMLLinkAccessible(aContent, aDoc)
  113. {
  114. // Make HTML area DOM element not accessible. HTML image map accessible
  115. // manages its tree itself.
  116. mStateFlags |= eNotNodeMapEntry;
  117. }
  118. ////////////////////////////////////////////////////////////////////////////////
  119. // HTMLAreaAccessible: Accessible
  120. ENameValueFlag
  121. HTMLAreaAccessible::NativeName(nsString& aName)
  122. {
  123. ENameValueFlag nameFlag = Accessible::NativeName(aName);
  124. if (!aName.IsEmpty())
  125. return nameFlag;
  126. if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName))
  127. Value(aName);
  128. return eNameOK;
  129. }
  130. void
  131. HTMLAreaAccessible::Description(nsString& aDescription)
  132. {
  133. aDescription.Truncate();
  134. // Still to do - follow IE's standard here
  135. nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(mContent));
  136. if (area)
  137. area->GetShape(aDescription);
  138. }
  139. ////////////////////////////////////////////////////////////////////////////////
  140. // HTMLAreaAccessible: Accessible public
  141. Accessible*
  142. HTMLAreaAccessible::ChildAtPoint(int32_t aX, int32_t aY,
  143. EWhichChildAtPoint aWhichChild)
  144. {
  145. // Don't walk into area accessibles.
  146. return this;
  147. }
  148. ////////////////////////////////////////////////////////////////////////////////
  149. // HTMLImageMapAccessible: HyperLinkAccessible
  150. uint32_t
  151. HTMLAreaAccessible::StartOffset()
  152. {
  153. // Image map accessible is not hypertext accessible therefore
  154. // StartOffset/EndOffset implementations of Accessible doesn't work here.
  155. // We return index in parent because image map contains area links only which
  156. // are embedded objects.
  157. // XXX: image map should be a hypertext accessible.
  158. return IndexInParent();
  159. }
  160. uint32_t
  161. HTMLAreaAccessible::EndOffset()
  162. {
  163. return IndexInParent() + 1;
  164. }
  165. nsRect
  166. HTMLAreaAccessible::RelativeBounds(nsIFrame** aBoundingFrame) const
  167. {
  168. nsIFrame* frame = GetFrame();
  169. if (!frame)
  170. return nsRect();
  171. nsImageFrame* imageFrame = do_QueryFrame(frame);
  172. nsImageMap* map = imageFrame->GetImageMap();
  173. nsRect bounds;
  174. nsresult rv = map->GetBoundsForAreaContent(mContent, bounds);
  175. if (NS_FAILED(rv))
  176. return nsRect();
  177. // XXX Areas are screwy; they return their rects as a pair of points, one pair
  178. // stored into the width and height.
  179. *aBoundingFrame = frame;
  180. bounds.width -= bounds.x;
  181. bounds.height -= bounds.y;
  182. return bounds;
  183. }