Bug 1322532: Platform a11y changes to enable handler-based live regions; r=tbsaunde

MozReview-Commit-ID: nNPvBy3ZGO

--HG--
extra : rebase_source : d8a797c9ddfb3d8ab4f13c9f2f261fba04320beb
extra : histedit_source : cc4f0bd8ba26cc88bcf9907f684e5d6c240d354f
This commit is contained in:
Aaron Klotz 2017-04-13 20:35:32 -06:00
Родитель 1de2299a3a
Коммит 0ee7073299
6 изменённых файлов: 97 добавлений и 0 удалений

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

@ -338,6 +338,21 @@ DocAccessibleParent::RecvTextChangeEvent(const uint64_t& aID,
return IPC_OK(); return IPC_OK();
} }
#if defined(XP_WIN)
mozilla::ipc::IPCResult
DocAccessibleParent::RecvSyncTextChangeEvent(const uint64_t& aID,
const nsString& aStr,
const int32_t& aStart,
const uint32_t& aLen,
const bool& aIsInsert,
const bool& aFromUser)
{
return RecvTextChangeEvent(aID, aStr, aStart, aLen, aIsInsert, aFromUser);
}
#endif // defined(XP_WIN)
mozilla::ipc::IPCResult mozilla::ipc::IPCResult
DocAccessibleParent::RecvSelectionEvent(const uint64_t& aID, DocAccessibleParent::RecvSelectionEvent(const uint64_t& aID,
const uint64_t& aWidgetID, const uint64_t& aWidgetID,

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

@ -88,6 +88,13 @@ public:
const bool& aIsInsert, const bool& aIsInsert,
const bool& aFromUser) override; const bool& aFromUser) override;
#if defined(XP_WIN)
virtual mozilla::ipc::IPCResult RecvSyncTextChangeEvent(const uint64_t& aID, const nsString& aStr,
const int32_t& aStart, const uint32_t& aLen,
const bool& aIsInsert,
const bool& aFromUser) override;
#endif // defined(XP_WIN)
virtual mozilla::ipc::IPCResult RecvSelectionEvent(const uint64_t& aID, virtual mozilla::ipc::IPCResult RecvSelectionEvent(const uint64_t& aID,
const uint64_t& aWidgetID, const uint64_t& aWidgetID,
const uint32_t& aType) override; const uint32_t& aType) override;

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

@ -190,6 +190,13 @@ DocAccessibleChild::SendTextChangeEvent(const uint64_t& aID,
const bool& aFromUser) const bool& aFromUser)
{ {
if (IsConstructedInParentProcess()) { if (IsConstructedInParentProcess()) {
if (aStr.Contains(L'\xfffc')) {
// The AT is going to need to reenter content while the event is being
// dispatched synchronously.
return PDocAccessibleChild::SendSyncTextChangeEvent(aID, aStr, aStart,
aLen, aIsInsert,
aFromUser);
}
return PDocAccessibleChild::SendTextChangeEvent(aID, aStr, aStart, return PDocAccessibleChild::SendTextChangeEvent(aID, aStr, aStart,
aLen, aIsInsert, aFromUser); aLen, aIsInsert, aFromUser);
} }

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

@ -43,6 +43,7 @@
#include "nsArrayUtils.h" #include "nsArrayUtils.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "nsIXULRuntime.h" #include "nsIXULRuntime.h"
#include "mozilla/mscom/AsyncInvoker.h"
#include "oleacc.h" #include "oleacc.h"
@ -1627,3 +1628,60 @@ AccessibleWrap::SetHandlerControl(DWORD aPid, RefPtr<IHandlerControl> aCtrl)
sHandlerControllers->AppendElement(Move(ctrlData)); sHandlerControllers->AppendElement(Move(ctrlData));
} }
bool
AccessibleWrap::DispatchTextChangeToHandler(bool aIsInsert,
const nsString& aText,
int32_t aStart, uint32_t aLen)
{
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
if (!sHandlerControllers || sHandlerControllers->IsEmpty()) {
return false;
}
HWND hwnd = GetHWNDFor(this);
MOZ_ASSERT(hwnd);
if (!hwnd) {
return false;
}
long msaaId = GetChildIDFor(this);
DWORD ourPid = ::GetCurrentProcessId();
// The handler ends up calling NotifyWinEvent, which should only be done once
// since it broadcasts the same event to every process who is subscribed.
// OTOH, if our chrome process contains a handler, we should prefer to
// broadcast the event from that process, as we want any DLLs injected by ATs
// to receive the event synchronously. Otherwise we simply choose the first
// handler in the list, for the lack of a better heuristic.
nsTArray<HandlerControllerData>::index_type ctrlIndex =
sHandlerControllers->IndexOf(ourPid);
if (ctrlIndex == nsTArray<HandlerControllerData>::NoIndex) {
ctrlIndex = 0;
}
HandlerControllerData& controller = sHandlerControllers->ElementAt(ctrlIndex);
MOZ_ASSERT(controller.mPid);
MOZ_ASSERT(controller.mCtrl);
VARIANT_BOOL isInsert = aIsInsert ? VARIANT_TRUE : VARIANT_FALSE;
IA2TextSegment textSegment{::SysAllocStringLen(aText.get(), aText.Length()),
aStart, static_cast<long>(aLen)};
ASYNC_INVOKER_FOR(IHandlerControl) invoker(controller.mCtrl,
Some(controller.mIsProxy));
HRESULT hr = ASYNC_INVOKE(invoker, OnTextChange, PtrToLong(hwnd), msaaId,
isInsert, &textSegment);
::SysFreeString(textSegment.text);
return SUCCEEDED(hr);
}

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

@ -192,6 +192,8 @@ public: // construction, destruction
static void SetHandlerControl(DWORD aPid, RefPtr<IHandlerControl> aCtrl); static void SetHandlerControl(DWORD aPid, RefPtr<IHandlerControl> aCtrl);
bool DispatchTextChangeToHandler(bool aIsInsert, const nsString& aText,
int32_t aStart, uint32_t aLen);
protected: protected:
virtual ~AccessibleWrap(); virtual ~AccessibleWrap();

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

@ -132,6 +132,14 @@ a11y::ProxyTextChangeEvent(ProxyAccessible* aText, const nsString& aStr,
return; return;
} }
static const bool useHandler =
Preferences::GetBool("accessibility.handler.enabled", false);
if (useHandler) {
wrapper->DispatchTextChangeToHandler(aInsert, aStr, aStart, aLen);
return;
}
auto text = static_cast<HyperTextAccessibleWrap*>(wrapper->AsHyperText()); auto text = static_cast<HyperTextAccessibleWrap*>(wrapper->AsHyperText());
if (text) { if (text) {
ia2AccessibleText::UpdateTextChangeData(text, aInsert, aStr, aStart, aLen); ia2AccessibleText::UpdateTextChangeData(text, aInsert, aStr, aStart, aLen);