Bug 1481922 - add support for select action and view selected event. r=eeejay, jchen

MozReview-Commit-ID: FaLz7majPhz
This commit is contained in:
Yura Zenevich 2018-08-09 11:08:41 -04:00
parent 26bb934fc5
commit 2b1f8c8ae8
5 changed files with 67 additions and 36 deletions

View File

@ -17,16 +17,17 @@ if (Utils.MozBuildApp === "mobile/android") {
const GECKOVIEW_MESSAGE = {
ACTIVATE: "GeckoView:AccessibilityActivate",
VIEW_FOCUSED: "GeckoView:AccessibilityViewFocused",
LONG_PRESS: "GeckoView:AccessibilityLongPress",
BY_GRANULARITY: "GeckoView:AccessibilityByGranularity",
CLIPBOARD: "GeckoView:AccessibilityClipboard",
EXPLORE_BY_TOUCH: "GeckoView:AccessibilityExploreByTouch",
LONG_PRESS: "GeckoView:AccessibilityLongPress",
NEXT: "GeckoView:AccessibilityNext",
PREVIOUS: "GeckoView:AccessibilityPrevious",
SCROLL_BACKWARD: "GeckoView:AccessibilityScrollBackward",
SCROLL_FORWARD: "GeckoView:AccessibilityScrollForward",
EXPLORE_BY_TOUCH: "GeckoView:AccessibilityExploreByTouch",
SELECT: "GeckoView:AccessibilitySelect",
SET_SELECTION: "GeckoView:AccessibilitySetSelection",
CLIPBOARD: "GeckoView:AccessibilityClipboard",
VIEW_FOCUSED: "GeckoView:AccessibilityViewFocused",
};
const ACCESSFU_MESSAGE = {
@ -238,6 +239,9 @@ var AccessFu = {
case GECKOVIEW_MESSAGE.CLIPBOARD:
this.Input.clipboard(data);
break;
case GECKOVIEW_MESSAGE.SELECT:
this.Input.selectCurrent(data);
break;
}
},
@ -348,6 +352,11 @@ var Input = {
mm.sendAsyncMessage("AccessFu:Activate", { offset: 0 });
},
selectCurrent: function selectCurrent(aData) {
let mm = Utils.getMessageManager();
mm.sendAsyncMessage("AccessFu:Select", aData);
},
doScroll: function doScroll(aDetails, aBrowser) {
let horizontal = aDetails.horizontal;
let page = aDetails.page;

View File

@ -33,15 +33,16 @@ function ContentControl(aContentScope) {
}
this.ContentControl.prototype = {
messagesOfInterest: ["AccessFu:MoveCursor",
"AccessFu:ClearCursor",
"AccessFu:MoveToPoint",
"AccessFu:AutoMove",
"AccessFu:Activate",
"AccessFu:MoveByGranularity",
messagesOfInterest: ["AccessFu:Activate",
"AccessFu:AndroidScroll",
"AccessFu:SetSelection",
"AccessFu:Clipboard"],
"AccessFu:AutoMove",
"AccessFu:ClearCursor",
"AccessFu:Clipboard",
"AccessFu:MoveByGranularity",
"AccessFu:MoveCursor",
"AccessFu:MoveToPoint",
"AccessFu:Select",
"AccessFu:SetSelection"],
start: function cc_start() {
let cs = this._contentScope.get();
@ -180,6 +181,16 @@ this.ContentControl.prototype = {
this.autoMove(null, aMessage.json);
},
handleSelect: function cc_handleSelect(aMessage) {
const vc = this.vc;
if (!this.sendToChild(vc, aMessage, null, true)) {
const acc = vc.position;
if (Utils.getState(acc).contains(States.SELECTABLE)) {
this.handleActivate(aMessage);
}
}
},
handleActivate: function cc_handleActivate(aMessage) {
let activateAccessible = (aAccessible) => {
Logger.debug(() => {
@ -222,7 +233,7 @@ this.ContentControl.prototype = {
if (!Utils.getState(aAccessible).contains(States.CHECKABLE) &&
!Utils.getState(aAccessible).contains(States.SELECTABLE)) {
this._contentScope.get().sendAsyncMessage("AccessFu:Present",
Presentation.actionInvoked(aAccessible, "click"));
Presentation.actionInvoked());
}
};

View File

@ -116,21 +116,16 @@ class AndroidPresentor {
*/
selected(aAccessible) {
return [{
eventType: AndroidEvents.VIEW_CLICKED,
eventType: AndroidEvents.VIEW_SELECTED,
selected: Utils.getState(aAccessible).contains(States.SELECTED)
}];
}
/**
* An object's action has been invoked.
* @param {nsIAccessible} aAccessible the object that has been invoked.
* @param {string} aActionName the name of the action.
*/
actionInvoked(aAccessible, aActionName) {
return [{
eventType: AndroidEvents.VIEW_CLICKED,
text: Utils.localize(UtteranceGenerator.genForAction(aAccessible, aActionName))
}];
actionInvoked() {
return [{ eventType: AndroidEvents.VIEW_CLICKED }];
}
/**

View File

@ -64,6 +64,7 @@ class AccessibilityTest : BaseSessionTest() {
fun onAccessibilityFocused(event: AccessibilityEvent) { }
fun onClicked(event: AccessibilityEvent) { }
fun onFocused(event: AccessibilityEvent) { }
fun onSelected(event: AccessibilityEvent) { }
fun onTextSelectionChanged(event: AccessibilityEvent) { }
fun onTextChanged(event: AccessibilityEvent) { }
fun onTextTraversal(event: AccessibilityEvent) { }
@ -90,6 +91,7 @@ class AccessibilityTest : BaseSessionTest() {
AccessibilityEvent.TYPE_VIEW_FOCUSED -> newDelegate.onFocused(event)
AccessibilityEvent.TYPE_VIEW_CLICKED -> newDelegate.onClicked(event)
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED -> newDelegate.onAccessibilityFocused(event)
AccessibilityEvent.TYPE_VIEW_SELECTED -> newDelegate.onSelected(event)
AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED -> newDelegate.onTextSelectionChanged(event)
AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED -> newDelegate.onTextChanged(event)
AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY -> newDelegate.onTextTraversal(event)
@ -204,21 +206,25 @@ class AccessibilityTest : BaseSessionTest() {
})
}
private fun waitUntilClick(checked: Boolean? = null, selected: Boolean? = null) {
private fun waitUntilClick(checked: Boolean) {
sessionRule.waitUntilCalled(object : EventDelegate {
@AssertCalled(count = 1)
override fun onClicked(event: AccessibilityEvent) {
var nodeId = getSourceId(event)
var node = provider.createAccessibilityNodeInfo(nodeId)
assertThat("Event's checked state matches", event.isChecked, equalTo(checked))
assertThat("Checkbox node has correct checked state", node.isChecked, equalTo(checked))
}
})
}
if (checked != null) {
assertThat("Event's checked state matches", event.isChecked, equalTo(checked))
assertThat("Checkbox node has correct checked state", node.isChecked, equalTo(checked))
}
if (selected != null) {
assertThat("Selectable node has correct selected state", node.isSelected, equalTo(selected))
}
private fun waitUntilSelect(selected: Boolean) {
sessionRule.waitUntilCalled(object : EventDelegate {
@AssertCalled(count = 1)
override fun onSelected(event: AccessibilityEvent) {
var nodeId = getSourceId(event)
var node = provider.createAccessibilityNodeInfo(nodeId)
assertThat("Selectable node has correct selected state", node.isSelected, equalTo(selected))
}
})
}
@ -407,10 +413,10 @@ class AccessibilityTest : BaseSessionTest() {
})
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null)
waitUntilClick(checked = true)
waitUntilClick(true)
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null)
waitUntilClick(checked = false)
waitUntilClick(false)
}
@Test fun testSelectable() {
@ -435,9 +441,15 @@ class AccessibilityTest : BaseSessionTest() {
})
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null)
waitUntilClick(selected = true)
waitUntilSelect(true)
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null)
waitUntilClick(selected = false)
waitUntilSelect(false)
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_SELECT, null)
waitUntilSelect(true)
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_SELECT, null)
waitUntilSelect(false)
}
}

View File

@ -189,6 +189,9 @@ public class SessionAccessibility {
case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD:
mSession.getEventDispatcher().dispatch("GeckoView:AccessibilityScrollBackward", null);
return true;
case AccessibilityNodeInfo.ACTION_SELECT:
mSession.getEventDispatcher().dispatch("GeckoView:AccessibilitySelect", null);
return true;
case AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT:
if (mLastItem) {
return false;
@ -483,8 +486,9 @@ public class SessionAccessibility {
// Bounds for the virtual content can be updated from any event.
updateBounds(mVirtualContentNode, message);
// State for the virtual content can be updated when view is clicked.
if (eventType == AccessibilityEvent.TYPE_VIEW_CLICKED) {
// State for the virtual content can be updated when view is clicked/selected.
if (eventType == AccessibilityEvent.TYPE_VIEW_CLICKED ||
eventType == AccessibilityEvent.TYPE_VIEW_SELECTED) {
updateState(mVirtualContentNode, message);
}
}