mirror of https://github.com/roytam1/UXP
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
209 lines
6.1 KiB
209 lines
6.1 KiB
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
/* 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; |
|
}
|
|
|