Bug 1322532: Add support for live regions to the com handler dll; r=tbsaunde

MozReview-Commit-ID: 1JPaUw5PrxU

--HG--
extra : rebase_source : e74cf6b3a2e9d78a3e939231ea06e0e3088fd538
This commit is contained in:
Aaron Klotz 2017-04-13 16:57:33 -06:00
Родитель c279528885
Коммит ba24d548f9
7 изменённых файлов: 627 добавлений и 39 удалений

Просмотреть файл

@ -12,6 +12,7 @@
#include "AccessibleHandler.h"
#include "AccessibleHandlerControl.h"
#include "AccessibleTextTearoff.h"
#include "Factory.h"
#include "HandlerData.h"
@ -183,6 +184,12 @@ AccessibleHandler::QueryHandlerInterface(IUnknown* aProxyUnknown, REFIID aIid,
return S_OK;
}
if (aIid == IID_IAccessibleText || aIid == IID_IAccessibleHypertext) {
RefPtr<IAccessibleHypertext> textTearoff(new AccessibleTextTearoff(this));
textTearoff.forget(aOutInterface);
return S_OK;
}
if (aIid == IID_IProvideClassInfo) {
RefPtr<IProvideClassInfo> clsInfo(this);
clsInfo.forget(aOutInterface);

Просмотреть файл

@ -22,6 +22,103 @@ namespace a11y {
mscom::SingletonFactory<AccessibleHandlerControl> gControlFactory;
namespace detail {
TextChange::TextChange()
: mIA2UniqueId(0)
, mIsInsert(false)
, mText()
{
}
TextChange::TextChange(long aIA2UniqueId, bool aIsInsert,
NotNull<IA2TextSegment*> aText)
: mIA2UniqueId(aIA2UniqueId)
, mIsInsert(aIsInsert)
, mText{BSTRCopy(aText->text), aText->start, aText->end}
{
}
TextChange::TextChange(TextChange&& aOther)
: mText()
{
*this = Move(aOther);
}
TextChange::TextChange(const TextChange& aOther)
: mText()
{
*this = aOther;
}
TextChange&
TextChange::operator=(TextChange&& aOther)
{
mIA2UniqueId = aOther.mIA2UniqueId;
mIsInsert = aOther.mIsInsert;
aOther.mIA2UniqueId = 0;
::SysFreeString(mText.text);
mText = aOther.mText;
aOther.mText.text = nullptr;
return *this;
}
TextChange&
TextChange::operator=(const TextChange& aOther)
{
mIA2UniqueId = aOther.mIA2UniqueId;
mIsInsert = aOther.mIsInsert;
::SysFreeString(mText.text);
mText = {BSTRCopy(aOther.mText.text), aOther.mText.start, aOther.mText.end};
return *this;
}
TextChange::~TextChange()
{
::SysFreeString(mText.text);
}
HRESULT
TextChange::GetOld(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutOldSegment)
{
if (mIsInsert || aIA2UniqueId != mIA2UniqueId) {
return S_OK;
}
return SegCopy(*aOutOldSegment, mText);
}
HRESULT
TextChange::GetNew(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutNewSegment)
{
if (!mIsInsert || aIA2UniqueId != mIA2UniqueId) {
return S_OK;
}
return SegCopy(*aOutNewSegment, mText);
}
/* static */ BSTR
TextChange::BSTRCopy(const BSTR& aIn)
{
return ::SysAllocStringLen(aIn, ::SysStringLen(aIn));
}
/* static */ HRESULT
TextChange::SegCopy(IA2TextSegment& aDest, const IA2TextSegment& aSrc)
{
aDest = {BSTRCopy(aSrc.text), aSrc.start, aSrc.end};
if (aSrc.text && !aDest.text) {
return E_OUTOFMEMORY;
}
if (!::SysStringLen(aDest.text)) {
return S_FALSE;
}
return S_OK;
}
} // namespace detail
HRESULT
AccessibleHandlerControl::Create(AccessibleHandlerControl** aOutObject)
{
@ -35,46 +132,14 @@ AccessibleHandlerControl::Create(AccessibleHandlerControl** aOutObject)
}
AccessibleHandlerControl::AccessibleHandlerControl()
: mRefCnt(0)
, mCacheGen(0)
: mCacheGen(0)
, mIA2Proxy(mscom::RegisterProxy(L"ia2marshal.dll"))
, mHandlerProxy(mscom::RegisterProxy())
{
MOZ_ASSERT(mIA2Proxy);
}
HRESULT
AccessibleHandlerControl::QueryInterface(REFIID aIid, void** aOutInterface)
{
if (!aOutInterface) {
return E_INVALIDARG;
}
if (aIid == IID_IUnknown || aIid == IID_IHandlerControl) {
RefPtr<IHandlerControl> ctl(this);
ctl.forget(aOutInterface);
return S_OK;
}
*aOutInterface = nullptr;
return E_NOINTERFACE;
}
ULONG
AccessibleHandlerControl::AddRef()
{
return ++mRefCnt;
}
ULONG
AccessibleHandlerControl::Release()
{
ULONG result = --mRefCnt;
if (!result) {
delete this;
}
return result;
}
IMPL_IUNKNOWN1(AccessibleHandlerControl, IHandlerControl)
HRESULT
AccessibleHandlerControl::Invalidate()
@ -83,6 +148,36 @@ AccessibleHandlerControl::Invalidate()
return S_OK;
}
HRESULT
AccessibleHandlerControl::OnTextChange(long aHwnd, long aIA2UniqueId,
VARIANT_BOOL aIsInsert,
IA2TextSegment* aText)
{
if (!aText) {
return E_INVALIDARG;
}
mTextChange = detail::TextChange(aIA2UniqueId, aIsInsert, WrapNotNull(aText));
NotifyWinEvent(aIsInsert ? IA2_EVENT_TEXT_INSERTED : IA2_EVENT_TEXT_REMOVED,
reinterpret_cast<HWND>(static_cast<uintptr_t>(aHwnd)),
OBJID_CLIENT, aIA2UniqueId);
return S_OK;
}
HRESULT
AccessibleHandlerControl::GetNewText(long aIA2UniqueId,
NotNull<IA2TextSegment*> aOutNewText)
{
return mTextChange.GetNew(aIA2UniqueId, aOutNewText);
}
HRESULT
AccessibleHandlerControl::GetOldText(long aIA2UniqueId,
NotNull<IA2TextSegment*> aOutOldText)
{
return mTextChange.GetOld(aIA2UniqueId, aOutOldText);
}
HRESULT
AccessibleHandlerControl::GetHandlerTypeInfo(ITypeInfo** aOutTypeInfo)
{

Просмотреть файл

@ -13,37 +13,70 @@
#include "Factory.h"
#include "HandlerData.h"
#include "IUnknownImpl.h"
#include "mozilla/mscom/Registration.h"
#include "mozilla/NotNull.h"
namespace mozilla {
namespace a11y {
namespace detail {
class TextChange final
{
public:
TextChange();
TextChange(long aIA2UniqueId, bool aIsInsert, NotNull<IA2TextSegment*> aText);
TextChange(TextChange&& aOther);
TextChange(const TextChange& aOther);
TextChange& operator=(TextChange&& aOther);
TextChange& operator=(const TextChange& aOther);
~TextChange();
HRESULT GetOld(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutOldSegment);
HRESULT GetNew(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutNewSegment);
private:
static BSTR BSTRCopy(const BSTR& aIn);
static HRESULT SegCopy(IA2TextSegment& aDest, const IA2TextSegment& aSrc);
long mIA2UniqueId;
bool mIsInsert;
IA2TextSegment mText;
};
} // namespace detail
class AccessibleHandlerControl final : public IHandlerControl
{
public:
static HRESULT Create(AccessibleHandlerControl** aOutObject);
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override;
STDMETHODIMP_(ULONG) AddRef() override;
STDMETHODIMP_(ULONG) Release() override;
DECL_IUNKNOWN
// IHandlerControl
STDMETHODIMP Invalidate() override;
STDMETHODIMP OnTextChange(long aHwnd, long aIA2UniqueId,
VARIANT_BOOL aIsInsert, IA2TextSegment* aText) override;
uint32_t GetCacheGen() const
{
return mCacheGen;
}
HRESULT GetNewText(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutNewText);
HRESULT GetOldText(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutOldText);
HRESULT GetHandlerTypeInfo(ITypeInfo** aOutTypeInfo);
private:
AccessibleHandlerControl();
~AccessibleHandlerControl() = default;
ULONG mRefCnt;
uint32_t mCacheGen;
detail::TextChange mTextChange;
UniquePtr<mscom::RegisteredProxy> mIA2Proxy;
UniquePtr<mscom::RegisteredProxy> mHandlerProxy;
};

Просмотреть файл

@ -0,0 +1,359 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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/. */
#if defined(MOZILLA_INTERNAL_API)
#error This code is NOT for internal Gecko use!
#endif // defined(MOZILLA_INTERNAL_API)
#include "AccessibleTextTearoff.h"
#include "AccessibleHandlerControl.h"
#include "AccessibleText_i.c"
#include "AccessibleHypertext_i.c"
#include "Factory.h"
#include "mozilla/Assertions.h"
namespace mozilla {
namespace a11y {
AccessibleTextTearoff::AccessibleTextTearoff(AccessibleHandler* aHandler)
: mHandler(aHandler)
{
MOZ_ASSERT(aHandler);
}
HRESULT
AccessibleTextTearoff::ResolveAccText()
{
if (mAccTextProxy) {
return S_OK;
}
RefPtr<IUnknown> proxy(mHandler->GetProxy());
if (!proxy) {
return E_UNEXPECTED;
}
return proxy->QueryInterface(IID_IAccessibleText,
getter_AddRefs(mAccTextProxy));
}
HRESULT
AccessibleTextTearoff::ResolveAccHypertext()
{
if (mAccHypertextProxy) {
return S_OK;
}
RefPtr<IUnknown> proxy(mHandler->GetProxy());
if (!proxy) {
return E_UNEXPECTED;
}
return proxy->QueryInterface(IID_IAccessibleHypertext,
getter_AddRefs(mAccHypertextProxy));
}
IMPL_IUNKNOWN_QUERY_HEAD(AccessibleTextTearoff)
IMPL_IUNKNOWN_QUERY_IFACE(IAccessibleText)
IMPL_IUNKNOWN_QUERY_IFACE(IAccessibleHypertext)
IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(mHandler)
HRESULT
AccessibleTextTearoff::addSelection(long startOffset, long endOffset)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->addSelection(startOffset, endOffset);
}
HRESULT
AccessibleTextTearoff::get_attributes(long offset, long *startOffset,
long *endOffset, BSTR *textAttributes)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_attributes(offset, startOffset, endOffset,
textAttributes);
}
HRESULT
AccessibleTextTearoff::get_caretOffset(long *offset)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_caretOffset(offset);
}
HRESULT
AccessibleTextTearoff::get_characterExtents(long offset,
enum IA2CoordinateType coordType,
long *x, long *y, long *width,
long *height)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_characterExtents(offset, coordType, x, y, width,
height);
}
HRESULT
AccessibleTextTearoff::get_nSelections(long *nSelections)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_nSelections(nSelections);
}
HRESULT
AccessibleTextTearoff::get_offsetAtPoint(long x, long y,
enum IA2CoordinateType coordType,
long *offset)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_offsetAtPoint(x, y, coordType, offset);
}
HRESULT
AccessibleTextTearoff::get_selection(long selectionIndex, long *startOffset,
long *endOffset)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_selection(selectionIndex, startOffset, endOffset);
}
HRESULT
AccessibleTextTearoff::get_text(long startOffset, long endOffset, BSTR *text)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_text(startOffset, endOffset, text);
}
HRESULT
AccessibleTextTearoff::get_textBeforeOffset(long offset,
enum IA2TextBoundaryType boundaryType,
long *startOffset, long *endOffset,
BSTR *text)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_textBeforeOffset(offset, boundaryType, startOffset,
endOffset, text);
}
HRESULT
AccessibleTextTearoff::get_textAfterOffset(long offset,
enum IA2TextBoundaryType boundaryType,
long *startOffset, long *endOffset,
BSTR *text)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_textAfterOffset(offset, boundaryType,
startOffset, endOffset, text);
}
HRESULT
AccessibleTextTearoff::get_textAtOffset(long offset,
enum IA2TextBoundaryType boundaryType,
long *startOffset, long *endOffset,
BSTR *text)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_textAtOffset(offset, boundaryType, startOffset,
endOffset, text);
}
HRESULT
AccessibleTextTearoff::removeSelection(long selectionIndex)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->removeSelection(selectionIndex);
}
HRESULT
AccessibleTextTearoff::setCaretOffset(long offset)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->setCaretOffset(offset);
}
HRESULT
AccessibleTextTearoff::setSelection(long selectionIndex, long startOffset,
long endOffset)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->setSelection(selectionIndex, startOffset, endOffset);
}
HRESULT
AccessibleTextTearoff::get_nCharacters(long *nCharacters)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->get_nCharacters(nCharacters);
}
HRESULT
AccessibleTextTearoff::scrollSubstringTo(long startIndex, long endIndex,
enum IA2ScrollType scrollType)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->scrollSubstringTo(startIndex, endIndex, scrollType);
}
HRESULT
AccessibleTextTearoff::scrollSubstringToPoint(long startIndex, long endIndex,
enum IA2CoordinateType coordinateType,
long x, long y)
{
HRESULT hr = ResolveAccText();
if (FAILED(hr)) {
return hr;
}
return mAccTextProxy->scrollSubstringToPoint(startIndex, endIndex,
coordinateType, x, y);
}
HRESULT
AccessibleTextTearoff::get_newText(IA2TextSegment *newText)
{
if (!newText) {
return E_INVALIDARG;
}
RefPtr<AccessibleHandlerControl> ctl(gControlFactory.GetSingleton());
MOZ_ASSERT(ctl);
if (!ctl) {
return S_OK;
}
long id;
HRESULT hr = mHandler->get_uniqueID(&id);
if (FAILED(hr)) {
return hr;
}
return ctl->GetNewText(id, WrapNotNull(newText));
}
HRESULT
AccessibleTextTearoff::get_oldText(IA2TextSegment *oldText)
{
if (!oldText) {
return E_INVALIDARG;
}
RefPtr<AccessibleHandlerControl> ctl(gControlFactory.GetSingleton());
MOZ_ASSERT(ctl);
if (!ctl) {
return S_OK;
}
long id;
HRESULT hr = mHandler->get_uniqueID(&id);
if (FAILED(hr)) {
return hr;
}
return ctl->GetOldText(id, WrapNotNull(oldText));
}
HRESULT
AccessibleTextTearoff::get_nHyperlinks(long *hyperlinkCount)
{
HRESULT hr = ResolveAccHypertext();
if (FAILED(hr)) {
return hr;
}
return mAccHypertextProxy->get_nHyperlinks(hyperlinkCount);
}
HRESULT
AccessibleTextTearoff::get_hyperlink(long index,
IAccessibleHyperlink **hyperlink)
{
HRESULT hr = ResolveAccHypertext();
if (FAILED(hr)) {
return hr;
}
return mAccHypertextProxy->get_hyperlink(index, hyperlink);
}
HRESULT
AccessibleTextTearoff::get_hyperlinkIndex(long charIndex, long *hyperlinkIndex)
{
HRESULT hr = ResolveAccHypertext();
if (FAILED(hr)) {
return hr;
}
return mAccHypertextProxy->get_hyperlinkIndex(charIndex, hyperlinkIndex);
}
} // namespace a11y
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,88 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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/. */
#if defined(MOZILLA_INTERNAL_API)
#error This code is NOT for internal Gecko use!
#endif // defined(MOZILLA_INTERNAL_API)
#ifndef mozilla_a11y_AccessibleTextTearoff_h
#define mozilla_a11y_AccessibleTextTearoff_h
#include "AccessibleHandler.h"
#include "AccessibleHypertext.h"
#include "IUnknownImpl.h"
#include "mozilla/RefPtr.h"
namespace mozilla {
namespace a11y {
class AccessibleTextTearoff final : public IAccessibleHypertext
{
public:
explicit AccessibleTextTearoff(AccessibleHandler* aHandler);
DECL_IUNKNOWN
// IAccessibleText
STDMETHODIMP addSelection(long startOffset, long endOffset) override;
STDMETHODIMP get_attributes(long offset, long *startOffset, long *endOffset,
BSTR *textAttributes) override;
STDMETHODIMP get_caretOffset(long *offset) override;
STDMETHODIMP get_characterExtents(long offset,
enum IA2CoordinateType coordType, long *x,
long *y, long *width, long *height) override;
STDMETHODIMP get_nSelections(long *nSelections) override;
STDMETHODIMP get_offsetAtPoint(long x, long y,
enum IA2CoordinateType coordType,
long *offset) override;
STDMETHODIMP get_selection(long selectionIndex, long *startOffset,
long *endOffset) override;
STDMETHODIMP get_text(long startOffset, long endOffset, BSTR *text) override;
STDMETHODIMP get_textBeforeOffset(long offset,
enum IA2TextBoundaryType boundaryType,
long *startOffset, long *endOffset,
BSTR *text) override;
STDMETHODIMP get_textAfterOffset(long offset,
enum IA2TextBoundaryType boundaryType,
long *startOffset, long *endOffset,
BSTR *text) override;
STDMETHODIMP get_textAtOffset(long offset,
enum IA2TextBoundaryType boundaryType,
long *startOffset, long *endOffset,
BSTR *text) override;
STDMETHODIMP removeSelection(long selectionIndex) override;
STDMETHODIMP setCaretOffset(long offset) override;
STDMETHODIMP setSelection(long selectionIndex, long startOffset,
long endOffset) override;
STDMETHODIMP get_nCharacters(long *nCharacters) override;
STDMETHODIMP scrollSubstringTo(long startIndex, long endIndex,
enum IA2ScrollType scrollType) override;
STDMETHODIMP scrollSubstringToPoint(long startIndex, long endIndex,
enum IA2CoordinateType coordinateType,
long x, long y) override;
STDMETHODIMP get_newText(IA2TextSegment *newText) override;
STDMETHODIMP get_oldText(IA2TextSegment *oldText) override;
// IAccessibleHypertext
STDMETHODIMP get_nHyperlinks(long *hyperlinkCount) override;
STDMETHODIMP get_hyperlink(long index,
IAccessibleHyperlink **hyperlink) override;
STDMETHODIMP get_hyperlinkIndex(long charIndex, long *hyperlinkIndex) override;
private:
~AccessibleTextTearoff() = default;
HRESULT ResolveAccText();
HRESULT ResolveAccHypertext();
RefPtr<AccessibleHandler> mHandler;
RefPtr<IAccessibleText> mAccTextProxy;
RefPtr<IAccessibleHypertext> mAccHypertextProxy;
};
} // namespace a11y
} // namespace mozilla
#endif // mozilla_a11y_AccessibleTextTearoff_h

Просмотреть файл

@ -9,6 +9,8 @@
import "ocidl.idl";
import "ServProv.idl";
import "AccessibleText.idl";
typedef struct _IA2Data
{
long mUniqueId;
@ -84,6 +86,9 @@ interface HandlerData
interface IHandlerControl : IUnknown
{
HRESULT Invalidate();
HRESULT OnTextChange([in] long aHwnd, [in] long aIA2UniqueId,
[in] VARIANT_BOOL aIsInsert,
[in] IA2TextSegment* aText);
}
[object,

Просмотреть файл

@ -20,6 +20,7 @@ SOURCES += [
'!HandlerData_p.c',
'AccessibleHandler.cpp',
'AccessibleHandlerControl.cpp',
'AccessibleTextTearoff.cpp',
]
GENERATED_FILES += [