mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 410765 – 'List all tabs' button on tabs not working in AT-SPI, r=MarcoZ, Olli.Pettay, aaronlev, sr=roc
This commit is contained in:
parent
ea248b175e
commit
8a1d46d679
@ -65,6 +65,7 @@
|
||||
#include "nsIEventStateManager.h"
|
||||
#include "nsISelection2.h"
|
||||
#include "nsISelectionController.h"
|
||||
#include "nsGUIEvent.h"
|
||||
|
||||
#include "nsContentCID.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
@ -291,6 +292,48 @@ nsAccUtils::HasListener(nsIContent *aContent, const nsAString& aEventType)
|
||||
return listenerManager && listenerManager->HasListenersFor(aEventType);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsAccUtils::DispatchMouseEvent(PRUint32 aEventType,
|
||||
nsIPresShell *aPresShell,
|
||||
nsIContent *aContent)
|
||||
{
|
||||
nsIFrame *frame = aPresShell->GetPrimaryFrameFor(aContent);
|
||||
if (!frame)
|
||||
return PR_FALSE;
|
||||
|
||||
nsIFrame* rootFrame = aPresShell->GetRootFrame();
|
||||
if (!rootFrame)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIWidget> rootWidget = rootFrame->GetWindow();
|
||||
if (!rootWidget)
|
||||
return PR_FALSE;
|
||||
|
||||
// Compute x and y coordinates.
|
||||
nsPoint point = frame->GetOffsetToExternal(rootFrame);
|
||||
nsSize size = frame->GetSize();
|
||||
|
||||
nsPresContext* presContext = aPresShell->GetPresContext();
|
||||
|
||||
PRInt32 x = presContext->AppUnitsToDevPixels(point.x + size.width / 2);
|
||||
PRInt32 y = presContext->AppUnitsToDevPixels(point.y + size.height / 2);
|
||||
|
||||
// Fire mouse event.
|
||||
nsMouseEvent event(PR_TRUE, aEventType, rootWidget,
|
||||
nsMouseEvent::eReal, nsMouseEvent::eNormal);
|
||||
|
||||
event.refPoint = nsIntPoint(x, y);
|
||||
|
||||
event.clickCount = 1;
|
||||
event.button = nsMouseEvent::eLeftButton;
|
||||
event.time = PR_IntervalNow();
|
||||
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
aPresShell->HandleEventWithTarget(&event, frame, aContent, &status);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsAccUtils::GetAccessKeyFor(nsIContent *aContent)
|
||||
{
|
||||
|
@ -124,6 +124,17 @@ public:
|
||||
*/
|
||||
static PRBool HasListener(nsIContent *aContent, const nsAString& aEventType);
|
||||
|
||||
/**
|
||||
* Send mouse events to the given element.
|
||||
*
|
||||
* @param aEventType an event type (see nsGUIEvent.h for constants)
|
||||
* @param aPresShell the presshell for the given element
|
||||
* @param aContent the element element
|
||||
*/
|
||||
static PRBool DispatchMouseEvent(PRUint32 aEventType,
|
||||
nsIPresShell *aPresShell,
|
||||
nsIContent *aContent);
|
||||
|
||||
/**
|
||||
* Return an accesskey registered on the given element by
|
||||
* nsIEventStateManager or 0 if there is no registered accesskey.
|
||||
|
@ -3137,40 +3137,30 @@ NS_IMETHODIMP nsAccessible::GetNativeInterface(void **aOutAccessible)
|
||||
|
||||
void nsAccessible::DoCommandCallback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
NS_ASSERTION(gDoCommandTimer, "How did we get here if there was no gDoCommandTimer?");
|
||||
NS_ASSERTION(gDoCommandTimer,
|
||||
"How did we get here if there was no gDoCommandTimer?");
|
||||
NS_RELEASE(gDoCommandTimer);
|
||||
|
||||
nsIContent *content = reinterpret_cast<nsIContent*>(aClosure);
|
||||
nsCOMPtr<nsIDOMXULElement> xulElement(do_QueryInterface(content));
|
||||
if (xulElement) {
|
||||
xulElement->Click();
|
||||
}
|
||||
else {
|
||||
nsIDocument *doc = content->GetDocument();
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIPresShell> presShell = doc->GetPrimaryShell();
|
||||
nsPIDOMWindow *outerWindow = doc->GetWindow();
|
||||
if (presShell && outerWindow) {
|
||||
nsAutoPopupStatePusher popupStatePusher(outerWindow, openAllowed);
|
||||
nsCOMPtr<nsIContent> content =
|
||||
reinterpret_cast<nsIContent*>(aClosure);
|
||||
|
||||
nsMouseEvent downEvent(PR_TRUE, NS_MOUSE_BUTTON_DOWN, nsnull,
|
||||
nsMouseEvent::eSynthesized);
|
||||
nsMouseEvent upEvent(PR_TRUE, NS_MOUSE_BUTTON_UP, nsnull,
|
||||
nsMouseEvent::eSynthesized);
|
||||
nsMouseEvent clickEvent(PR_TRUE, NS_MOUSE_CLICK, nsnull,
|
||||
nsMouseEvent::eSynthesized);
|
||||
nsIDocument *doc = content->GetDocument();
|
||||
if (!doc)
|
||||
return;
|
||||
|
||||
nsEventStatus eventStatus = nsEventStatus_eIgnore;
|
||||
content->DispatchDOMEvent(&downEvent, nsnull,
|
||||
presShell->GetPresContext(), &eventStatus);
|
||||
content->DispatchDOMEvent(&upEvent, nsnull,
|
||||
presShell->GetPresContext(), &eventStatus);
|
||||
content->DispatchDOMEvent(&clickEvent, nsnull,
|
||||
presShell->GetPresContext(), &eventStatus);
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIPresShell> presShell = doc->GetPrimaryShell();
|
||||
|
||||
// Scroll into view.
|
||||
presShell->ScrollContentIntoView(content, NS_PRESSHELL_SCROLL_ANYWHERE,
|
||||
NS_PRESSHELL_SCROLL_ANYWHERE);
|
||||
|
||||
// Fire mouse down and mouse up events.
|
||||
PRBool res = nsAccUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, presShell,
|
||||
content);
|
||||
if (!res)
|
||||
return;
|
||||
|
||||
nsAccUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_UP, presShell, content);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -56,6 +56,7 @@ _TEST_FILES =\
|
||||
test_cssattrs.html \
|
||||
test_groupattrs.xul \
|
||||
$(warning test_table_indexes.html temporarily disabled) \
|
||||
test_nsIAccessible_actions.xul \
|
||||
test_nsIAccessible_name.html \
|
||||
test_nsIAccessible_name.xul \
|
||||
test_nsIAccessibleTable_1.html \
|
||||
|
229
accessible/tests/mochitest/test_nsIAccessible_actions.xul
Normal file
229
accessible/tests/mochitest/test_nsIAccessible_actions.xul
Normal file
@ -0,0 +1,229 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/a11y/accessible/nsIAccessible_name.css"
|
||||
type="text/css"?>
|
||||
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="Accessibility Name Calculating Test.">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
|
||||
const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole;
|
||||
|
||||
// Event constants
|
||||
const MOUSEDOWN_EVENT = 1;
|
||||
const MOUSEUP_EVENT = 2;
|
||||
const CLICK_EVENT = 4;
|
||||
const COMMAND_EVENT = 8;
|
||||
|
||||
const CLICK_EVENTS = MOUSEDOWN_EVENT | MOUSEUP_EVENT | CLICK_EVENT;
|
||||
const ALL_EVENTS = CLICK_EVENTS | COMMAND_EVENT;
|
||||
|
||||
var gAccRetrieval = null;
|
||||
|
||||
var gEventHandler = {
|
||||
initialize: function(aID, aElm, aExpectedEvents)
|
||||
{
|
||||
this.ID = aID,
|
||||
this.element = aElm;
|
||||
this.mExpectedEvents = aExpectedEvents;
|
||||
this.mFiredEvents = 0;
|
||||
|
||||
if (this.mExpectedEvents & MOUSEDOWN_EVENT)
|
||||
aElm.addEventListener("mousedown", this, false);
|
||||
|
||||
if (this.mExpectedEvents & MOUSEUP_EVENT)
|
||||
aElm.addEventListener("mouseup", this, false);
|
||||
|
||||
if (this.mExpectedEvents & CLICK_EVENT)
|
||||
aElm.addEventListener("click", this, false);
|
||||
|
||||
if (this.mExpectedEvents & COMMAND_EVENT)
|
||||
aElm.addEventListener("command", this, false);
|
||||
},
|
||||
|
||||
checkEvents: function()
|
||||
{
|
||||
if (this.mExpectedEvents & MOUSEDOWN_EVENT) {
|
||||
ok(this.mFiredEvents & MOUSEDOWN_EVENT,
|
||||
"mousedown hasn't been fired for " + this.ID);
|
||||
this.element.removeEventListener("mousedown", this, false);
|
||||
}
|
||||
|
||||
if (this.mExpectedEvents & MOUSEUP_EVENT) {
|
||||
ok(this.mFiredEvents & MOUSEUP_EVENT,
|
||||
"mouseup hasn't been fired for " + this.ID);
|
||||
this.element.removeEventListener("mouseup", this, false);
|
||||
}
|
||||
|
||||
if (this.mExpectedEvents & CLICK_EVENT) {
|
||||
ok(this.mFiredEvents & CLICK_EVENT,
|
||||
"click hasn't been fired for " + this.ID);
|
||||
this.element.removeEventListener("click", this, false);
|
||||
}
|
||||
|
||||
if (this.mExpectedEvents & COMMAND_EVENT) {
|
||||
ok(this.mFiredEvents & COMMAND_EVENT,
|
||||
"command hasn't been fired for " + this.ID);
|
||||
this.element.removeEventListener("command", this, false);
|
||||
}
|
||||
},
|
||||
|
||||
ID: "",
|
||||
element: null,
|
||||
|
||||
handleEvent : function(aEvent)
|
||||
{
|
||||
if (aEvent.type == "mousedown")
|
||||
this.mFiredEvents |= MOUSEDOWN_EVENT;
|
||||
else if(aEvent.type == "mouseup")
|
||||
this.mFiredEvents |= MOUSEUP_EVENT;
|
||||
else if(aEvent.type == "click")
|
||||
this.mFiredEvents |= CLICK_EVENT;
|
||||
else if(aEvent.type == "command")
|
||||
this.mFiredEvents |= COMMAND_EVENT;
|
||||
},
|
||||
|
||||
mExpectedEvents: 0,
|
||||
mFiredEvents: 0
|
||||
};
|
||||
|
||||
function testActions(aArray, aIndex)
|
||||
{
|
||||
if (!aIndex)
|
||||
aIndex = 0;
|
||||
|
||||
if (aIndex == aArray.length) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var ID = aArray[aIndex].ID;
|
||||
var actionName = aArray[aIndex].actionName;
|
||||
var events = aArray[aIndex].events;
|
||||
|
||||
var elm = document.getElementById(ID);
|
||||
if (!elm) {
|
||||
ok(false, "There is no element with ID " + ID);
|
||||
SimpleTest.finish();
|
||||
return null;
|
||||
}
|
||||
|
||||
var acc = null;
|
||||
try {
|
||||
acc = gAccRetrieval.getAccessibleFor(elm);
|
||||
} catch(e) {
|
||||
}
|
||||
|
||||
if (!acc) {
|
||||
ok(false, "There is no accessible for " + ID);
|
||||
SimpleTest.finish();
|
||||
return null;
|
||||
}
|
||||
|
||||
is(acc.getActionName(0), actionName,
|
||||
"Wrong action name of the accessible for " + ID);
|
||||
|
||||
gEventHandler.initialize(ID, elm, events);
|
||||
|
||||
acc.doAction(0);
|
||||
|
||||
window.setTimeout(
|
||||
function()
|
||||
{
|
||||
gEventHandler.checkEvents();
|
||||
testActions(aArray, aIndex + 1);
|
||||
},
|
||||
200
|
||||
);
|
||||
}
|
||||
|
||||
function doTest()
|
||||
{
|
||||
gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
|
||||
getService(nsIAccessibleRetrieval);
|
||||
|
||||
var actionsArray = [
|
||||
{
|
||||
ID: "menu",
|
||||
actionName: "click",
|
||||
events: CLICK_EVENTS
|
||||
},
|
||||
{
|
||||
ID: "submenu",
|
||||
actionName: "click",
|
||||
events: CLICK_EVENTS
|
||||
},
|
||||
{
|
||||
ID: "menuitem",
|
||||
actionName: "click",
|
||||
events: ALL_EVENTS
|
||||
},
|
||||
{
|
||||
ID: "button",
|
||||
actionName: "press",
|
||||
events: ALL_EVENTS
|
||||
},
|
||||
{
|
||||
ID: "buttonmenu",
|
||||
actionName: "press",
|
||||
events: CLICK_EVENTS
|
||||
},
|
||||
{
|
||||
ID: "buttonmenu_item",
|
||||
actionName: "click",
|
||||
events: CLICK_EVENTS
|
||||
}
|
||||
];
|
||||
testActions(actionsArray);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(doTest);
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=444279"
|
||||
title="mochitest for accessible name calculating">
|
||||
Mozilla Bug 444279
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
<menubar>
|
||||
<menu label="menu" id="menu">
|
||||
<menupopup>
|
||||
<menuitem label="menu item" id="menuitem"/>
|
||||
<menu label="submenu" id="submenu">
|
||||
<menupopup>
|
||||
<menuitem label="menu item"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</menubar>
|
||||
|
||||
<button label="button" id="button"/>
|
||||
|
||||
<button type="menu" id="buttonmenu" label="button">
|
||||
<menupopup>
|
||||
<menuitem label="item1" id="buttonmenu_item"/>
|
||||
<menuitem label="item1"/>
|
||||
</menupopup>
|
||||
</button>
|
||||
</window>
|
||||
|
Loading…
Reference in New Issue
Block a user