зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1479039 - Update cached focus path bounds on scroll. r=snorp,yzen a=jcristau
Differential Revision: https://phabricator.services.mozilla.com/D11216 --HG-- extra : source : b47fdd1194c70c21906769611e2abf1d3e8a0781 extra : histedit_source : 896e567a19427b716dec3de3942ee97ec7ff1ac0
This commit is contained in:
Родитель
683a26d69e
Коммит
1738380f30
|
@ -76,6 +76,9 @@ DocAccessibleWrap::HandleAccEvent(AccEvent* aEvent)
|
|||
case nsIAccessibleEvent::EVENT_SCROLLING_END:
|
||||
CacheViewport();
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_SCROLLING:
|
||||
UpdateFocusPathBounds();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -195,6 +198,7 @@ DocAccessibleWrap::GetTopLevelContentDoc(AccessibleWrap* aAccessible) {
|
|||
void
|
||||
DocAccessibleWrap::CacheFocusPath(AccessibleWrap* aAccessible)
|
||||
{
|
||||
mFocusPath.Clear();
|
||||
if (IPCAccessibilityActive()) {
|
||||
DocAccessibleChild* ipcDoc = IPCDoc();
|
||||
nsTArray<BatchData> cacheData;
|
||||
|
@ -223,6 +227,7 @@ DocAccessibleWrap::CacheFocusPath(AccessibleWrap* aAccessible)
|
|||
acc->MaxValue(),
|
||||
acc->Step(),
|
||||
attributes));
|
||||
mFocusPath.Put(acc->UniqueID(), acc);
|
||||
}
|
||||
|
||||
ipcDoc->SendBatch(eBatch_FocusPath, cacheData);
|
||||
|
@ -236,3 +241,42 @@ DocAccessibleWrap::CacheFocusPath(AccessibleWrap* aAccessible)
|
|||
sessionAcc->ReplaceFocusPathCache(accessibles);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DocAccessibleWrap::UpdateFocusPathBounds()
|
||||
{
|
||||
if (!mFocusPath.Count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (IPCAccessibilityActive()) {
|
||||
DocAccessibleChild* ipcDoc = IPCDoc();
|
||||
nsTArray<BatchData> boundsData(mFocusPath.Count());
|
||||
for (auto iter = mFocusPath.Iter(); !iter.Done(); iter.Next()) {
|
||||
Accessible* accessible = iter.Data();
|
||||
auto uid = accessible->IsDoc() && accessible->AsDoc()->IPCDoc() ? 0
|
||||
: reinterpret_cast<uint64_t>(accessible->UniqueID());
|
||||
boundsData.AppendElement(BatchData(accessible->Document()->IPCDoc(),
|
||||
uid,
|
||||
0,
|
||||
accessible->Bounds(),
|
||||
nsString(),
|
||||
nsString(),
|
||||
nsString(),
|
||||
UnspecifiedNaN<double>(),
|
||||
UnspecifiedNaN<double>(),
|
||||
UnspecifiedNaN<double>(),
|
||||
UnspecifiedNaN<double>(),
|
||||
nsTArray<Attribute>()));
|
||||
}
|
||||
|
||||
ipcDoc->SendBatch(eBatch_BoundsUpdate, boundsData);
|
||||
} else if (SessionAccessibility* sessionAcc = SessionAccessibility::GetInstanceFor(this)) {
|
||||
nsTArray<AccessibleWrap*> accessibles(mFocusPath.Count());
|
||||
for (auto iter = mFocusPath.Iter(); !iter.Done(); iter.Next()) {
|
||||
accessibles.AppendElement(static_cast<AccessibleWrap*>(iter.Data().get()));
|
||||
}
|
||||
|
||||
sessionAcc->UpdateCachedBounds(accessibles);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ public:
|
|||
enum {
|
||||
eBatch_Viewport = 0,
|
||||
eBatch_FocusPath = 1,
|
||||
eBatch_BoundsUpdate = 2,
|
||||
};
|
||||
|
||||
protected:
|
||||
|
@ -50,9 +51,13 @@ protected:
|
|||
private:
|
||||
void CacheViewport();
|
||||
|
||||
void UpdateFocusPathBounds();
|
||||
|
||||
static void CacheViewportCallback(nsITimer* aTimer, void* aDocAccParam);
|
||||
|
||||
nsCOMPtr<nsITimer> mCacheRefreshTimer;
|
||||
|
||||
AccessibleHashtable mFocusPath;
|
||||
};
|
||||
|
||||
} // namespace a11y
|
||||
|
|
|
@ -224,6 +224,9 @@ a11y::ProxyBatch(ProxyAccessible* aDocument,
|
|||
case DocAccessibleWrap::eBatch_FocusPath:
|
||||
sessionAcc->ReplaceFocusPathCache(accWraps, aData);
|
||||
break;
|
||||
case DocAccessibleWrap::eBatch_BoundsUpdate:
|
||||
sessionAcc->UpdateCachedBounds(accWraps, aData);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown batch type.");
|
||||
break;
|
||||
|
|
|
@ -373,3 +373,22 @@ SessionAccessibility::ReplaceFocusPathCache(const nsTArray<AccessibleWrap*>& aAc
|
|||
|
||||
mSessionAccessibility->ReplaceFocusPathCache(infos);
|
||||
}
|
||||
|
||||
void
|
||||
SessionAccessibility::UpdateCachedBounds(const nsTArray<AccessibleWrap*>& aAccessibles,
|
||||
const nsTArray<BatchData>& aData)
|
||||
{
|
||||
auto infos = jni::ObjectArray::New<java::GeckoBundle>(aAccessibles.Length());
|
||||
for (size_t i = 0; i < aAccessibles.Length(); i++) {
|
||||
AccessibleWrap* acc = aAccessibles.ElementAt(i);
|
||||
if (aData.Length() == aAccessibles.Length()) {
|
||||
const BatchData& data = aData.ElementAt(i);
|
||||
auto bundle = acc->ToSmallBundle(data.State(), data.Bounds());
|
||||
infos->SetElement(i, bundle);
|
||||
} else {
|
||||
infos->SetElement(i, acc->ToSmallBundle());
|
||||
}
|
||||
}
|
||||
|
||||
mSessionAccessibility->UpdateCachedBounds(infos);
|
||||
}
|
||||
|
|
|
@ -112,6 +112,9 @@ public:
|
|||
void ReplaceFocusPathCache(const nsTArray<AccessibleWrap*>& aAccessibles,
|
||||
const nsTArray<BatchData>& aData = nsTArray<BatchData>());
|
||||
|
||||
void UpdateCachedBounds(const nsTArray<AccessibleWrap*>& aAccessibles,
|
||||
const nsTArray<BatchData>& aData = nsTArray<BatchData>());
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SessionAccessibility)
|
||||
|
||||
private:
|
||||
|
|
|
@ -33,6 +33,7 @@ import android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo;
|
|||
import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo;
|
||||
import android.view.accessibility.AccessibilityNodeProvider;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class SessionAccessibility {
|
||||
|
@ -250,10 +251,6 @@ public class SessionAccessibility {
|
|||
return node;
|
||||
}
|
||||
|
||||
private boolean isNodeCached(final int virtualViewId) {
|
||||
return mViewportCache.get(virtualViewId) != null || mFocusPathCache.get(virtualViewId) != null;
|
||||
}
|
||||
|
||||
private synchronized AccessibilityNodeInfo getNodeFromCache(final int virtualViewId) {
|
||||
AccessibilityNodeInfo node = null;
|
||||
for (SparseArray<GeckoBundle> cache : mCaches) {
|
||||
|
@ -352,7 +349,7 @@ public class SessionAccessibility {
|
|||
int[] children = nodeInfo.getIntArray("children");
|
||||
if (children != null) {
|
||||
for (int childId : children) {
|
||||
if (!fromCache || isNodeCached(childId)) {
|
||||
if (!fromCache || getMostRecentBundle(childId) != null) {
|
||||
// If this node is from cache, only populate with children that are cached as well.
|
||||
node.addChild(mView, childId);
|
||||
}
|
||||
|
@ -664,6 +661,18 @@ public class SessionAccessibility {
|
|||
((ViewParent) mView).requestSendAccessibilityEvent(mView, event);
|
||||
}
|
||||
|
||||
private synchronized GeckoBundle getMostRecentBundle(final int virtualViewId) {
|
||||
Iterator<SparseArray<GeckoBundle>> iter = mCaches.descendingIterator();
|
||||
while (iter.hasNext()) {
|
||||
GeckoBundle bundle = iter.next().get(virtualViewId);
|
||||
if (bundle != null) {
|
||||
return bundle;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/* package */ final class NativeProvider extends JNIObject {
|
||||
@WrapForJNI(calledFrom = "ui")
|
||||
private void setAttached(final boolean attached) {
|
||||
|
@ -713,5 +722,17 @@ public class SessionAccessibility {
|
|||
mCaches.remove(mFocusPathCache);
|
||||
mCaches.add(mFocusPathCache);
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private synchronized void updateCachedBounds(final GeckoBundle[] bundles) {
|
||||
for (GeckoBundle bundle : bundles) {
|
||||
GeckoBundle cachedBundle = getMostRecentBundle(bundle.getInt("id"));
|
||||
if (cachedBundle == null) {
|
||||
Log.e(LOGTAG, "Can't update bounds of uncached node " + bundle.getInt("id"));
|
||||
continue;
|
||||
}
|
||||
cachedBundle.putIntArray("bounds", bundle.getIntArray("bounds"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче