summaryrefslogtreecommitdiffstats
path: root/accessible/windows/sdn/sdnTextAccessible.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/windows/sdn/sdnTextAccessible.cpp')
-rw-r--r--accessible/windows/sdn/sdnTextAccessible.cpp210
1 files changed, 210 insertions, 0 deletions
diff --git a/accessible/windows/sdn/sdnTextAccessible.cpp b/accessible/windows/sdn/sdnTextAccessible.cpp
new file mode 100644
index 000000000..b51caf44e
--- /dev/null
+++ b/accessible/windows/sdn/sdnTextAccessible.cpp
@@ -0,0 +1,210 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "sdnTextAccessible.h"
+
+#include "ISimpleDOMText_i.c"
+
+#include "nsCoreUtils.h"
+#include "DocAccessible.h"
+
+#include "nsIFrame.h"
+#include "nsFontMetrics.h"
+#include "nsPresContext.h"
+#include "nsLayoutUtils.h"
+#include "nsRange.h"
+#include "gfxFont.h"
+#include "nsIAccessibleTypes.h"
+#include "mozilla/gfx/2D.h"
+
+using namespace mozilla::a11y;
+
+////////////////////////////////////////////////////////////////////////////////
+// sdnTextAccessible
+////////////////////////////////////////////////////////////////////////////////
+
+IMPL_IUNKNOWN_QUERY_HEAD(sdnTextAccessible)
+ IMPL_IUNKNOWN_QUERY_IFACE(ISimpleDOMText)
+IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(mAccessible)
+
+STDMETHODIMP
+sdnTextAccessible::get_domText(BSTR __RPC_FAR* aText)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aText)
+ return E_INVALIDARG;
+ *aText = nullptr;
+
+ if (mAccessible->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ nsAutoString nodeValue;
+
+ nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(mAccessible->GetContent()));
+ DOMNode->GetNodeValue(nodeValue);
+ if (nodeValue.IsEmpty())
+ return S_FALSE;
+
+ *aText = ::SysAllocStringLen(nodeValue.get(), nodeValue.Length());
+ return *aText ? S_OK : E_OUTOFMEMORY;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+sdnTextAccessible::get_clippedSubstringBounds(unsigned int aStartIndex,
+ unsigned int aEndIndex,
+ int __RPC_FAR* aX,
+ int __RPC_FAR* aY,
+ int __RPC_FAR* aWidth,
+ int __RPC_FAR* aHeight)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ nscoord x = 0, y = 0, width = 0, height = 0;
+ HRESULT rv = get_unclippedSubstringBounds(aStartIndex, aEndIndex,
+ &x, &y, &width, &height);
+ if (FAILED(rv))
+ return rv;
+
+ DocAccessible* document = mAccessible->Document();
+ NS_ASSERTION(document,
+ "There must always be a doc accessible, but there isn't. Crash!");
+
+ nsIntRect docRect = document->Bounds();
+ nsIntRect unclippedRect(x, y, width, height);
+
+ nsIntRect clippedRect;
+ clippedRect.IntersectRect(unclippedRect, docRect);
+
+ *aX = clippedRect.x;
+ *aY = clippedRect.y;
+ *aWidth = clippedRect.width;
+ *aHeight = clippedRect.height;
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+sdnTextAccessible::get_unclippedSubstringBounds(unsigned int aStartIndex,
+ unsigned int aEndIndex,
+ int __RPC_FAR* aX,
+ int __RPC_FAR* aY,
+ int __RPC_FAR* aWidth,
+ int __RPC_FAR* aHeight)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aX || !aY || !aWidth || !aHeight)
+ return E_INVALIDARG;
+ *aX = *aY = *aWidth = *aHeight = 0;
+
+ if (mAccessible->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ nsIFrame *frame = mAccessible->GetFrame();
+ NS_ENSURE_TRUE(frame, E_FAIL);
+
+ nsPoint startPoint, endPoint;
+ nsIFrame* startFrame = GetPointFromOffset(frame, aStartIndex, true, startPoint);
+ nsIFrame* endFrame = GetPointFromOffset(frame, aEndIndex, false, endPoint);
+ if (!startFrame || !endFrame)
+ return E_FAIL;
+
+ nsRect sum;
+ nsIFrame* iter = startFrame;
+ nsIFrame* stopLoopFrame = endFrame->GetNextContinuation();
+ for (; iter != stopLoopFrame; iter = iter->GetNextContinuation()) {
+ nsRect rect = iter->GetScreenRectInAppUnits();
+ nscoord start = (iter == startFrame) ? startPoint.x : 0;
+ nscoord end = (iter == endFrame) ? endPoint.x : rect.width;
+ rect.x += start;
+ rect.width = end - start;
+ sum.UnionRect(sum, rect);
+ }
+
+ nsPresContext* presContext = mAccessible->Document()->PresContext();
+ *aX = presContext->AppUnitsToDevPixels(sum.x);
+ *aY = presContext->AppUnitsToDevPixels(sum.y);
+ *aWidth = presContext->AppUnitsToDevPixels(sum.width);
+ *aHeight = presContext->AppUnitsToDevPixels(sum.height);
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+sdnTextAccessible::scrollToSubstring(unsigned int aStartIndex,
+ unsigned int aEndIndex)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (mAccessible->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ RefPtr<nsRange> range = new nsRange(mAccessible->GetContent());
+ if (NS_FAILED(range->SetStart(mAccessible->GetContent(), aStartIndex)))
+ return E_FAIL;
+
+ if (NS_FAILED(range->SetEnd(mAccessible->GetContent(), aEndIndex)))
+ return E_FAIL;
+
+ nsresult rv =
+ nsCoreUtils::ScrollSubstringTo(mAccessible->GetFrame(), range,
+ nsIAccessibleScrollType::SCROLL_TYPE_ANYWHERE);
+ return GetHRESULT(rv);
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+sdnTextAccessible::get_fontFamily(BSTR __RPC_FAR* aFontFamily)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aFontFamily)
+ return E_INVALIDARG;
+ *aFontFamily = nullptr;
+
+ if (mAccessible->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ nsIFrame* frame = mAccessible->GetFrame();
+ if (!frame)
+ return E_FAIL;
+
+ RefPtr<nsFontMetrics> fm =
+ nsLayoutUtils::GetFontMetricsForFrame(frame, 1.0f);
+
+ const nsString& name =
+ fm->GetThebesFontGroup()->GetFirstValidFont()->GetName();
+ if (name.IsEmpty())
+ return S_FALSE;
+
+ *aFontFamily = ::SysAllocStringLen(name.get(), name.Length());
+ return *aFontFamily ? S_OK : E_OUTOFMEMORY;
+
+ A11Y_TRYBLOCK_END
+}
+
+nsIFrame*
+sdnTextAccessible::GetPointFromOffset(nsIFrame* aContainingFrame,
+ int32_t aOffset,
+ bool aPreferNext,
+ nsPoint& aOutPoint)
+{
+ nsIFrame* textFrame = nullptr;
+ int32_t outOffset;
+ aContainingFrame->GetChildFrameContainingOffset(aOffset, aPreferNext,
+ &outOffset, &textFrame);
+ if (textFrame)
+ textFrame->GetPointFromOffset(aOffset, &aOutPoint);
+
+ return textFrame;
+}