Bug 283482. MSAA events and objects in wrong HWND for CSS overflow children. r=bz, sr=roc

This commit is contained in:
aaronleventhal%moonset.net 2005-03-02 19:05:09 +00:00
parent 81cd248f48
commit d6b4a62ca7
10 changed files with 71 additions and 60 deletions

View File

@ -38,9 +38,12 @@
#include "nsISupports.idl"
interface nsIFrame;
[scriptable, uuid(b3507946-4a44-4e40-b66c-f23e320997c5)]
interface nsPIAccessNode : nsISupports
{
[noscript] void init();
[noscript] void shutdown();
[notxpcom] nsIFrame GetFrame();
};

View File

@ -247,16 +247,25 @@ already_AddRefed<nsIAccessibleDocument> nsAccessNode::GetDocAccessible()
return docAccessible;
}
nsIFrame* nsAccessNode::GetFrame()
{
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
if (!shell)
return nsnull;
nsIFrame* frame = nsnull;
nsIFrame* frame;
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
shell->GetPrimaryFrameFor(content, &frame);
return frame;
while (content) {
shell->GetPrimaryFrameFor(content, &frame);
if (frame) {
return frame;
}
nsCOMPtr<nsIContent> tempContent = content->GetParent();
content = tempContent;
}
return nsnull;
}
NS_IMETHODIMP

View File

@ -125,7 +125,6 @@ protected:
already_AddRefed<nsIPresShell> GetPresShell();
nsPresContext* GetPresContext();
already_AddRefed<nsIAccessibleDocument> GetDocAccessible();
virtual nsIFrame* GetFrame();
nsCOMPtr<nsIDOMNode> mDOMNode;
nsCOMPtr<nsIWeakReference> mWeakShell;

View File

@ -592,7 +592,7 @@ PRBool nsAccessible::IsPartiallyVisible(PRBool *aIsOffscreen)
if (rectVisibility == nsRectVisibility_kVisible)
return PR_TRUE;
*aIsOffscreen = PR_TRUE;
*aIsOffscreen = rectVisibility != nsRectVisibility_kZeroAreaRect;
return PR_FALSE;
}
@ -1351,18 +1351,17 @@ nsRoleMapEntry nsAccessible::gWAIRoleMap[] =
{"button", ROLE_PUSHBUTTON, eAggregateSubtree, 0, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
{"checkbox", ROLE_CHECKBUTTON, eAggregateSubtree, 0, {"checked", "true", STATE_CHECKED}, {"readonly", 0, STATE_READONLY}, {0, 0, 0}},
{"checkbox-tristate", ROLE_CHECKBUTTON, eAggregateSubtree, 0, {"checked", "true", STATE_CHECKED}, {"checked", "mixed", STATE_MIXED}, {"readonly", 0, STATE_READONLY}},
{"columnheader", ROLE_COLUMNHEADER, eAggregateSubtree, STATE_SELECTABLE, {"selected", 0, STATE_SELECTED}, {0, 0, 0}, {0, 0, 0}},
{"columnheader", ROLE_COLUMNHEADER, eAggregateSubtree, STATE_SELECTABLE, {"selected", 0, STATE_SELECTED}, {"readonly", 0, STATE_READONLY}, {0, 0, 0}},
{"icon", ROLE_ICON, eAggregateSubtree, 0, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
{"menugroup", ROLE_MENUPOPUP, eTitleOnly, 0, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
{"menupopup", ROLE_MENUPOPUP, eTitleOnly, 0, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
{"menu", ROLE_MENUPOPUP, eTitleOnly, 0, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
{"menubar", ROLE_MENUBAR, eTitleOnly, 0, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
{"menuitem", ROLE_MENUITEM, eAggregateSubtree, 0, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
{"menuitem-checkbox", ROLE_MENUITEM, eAggregateSubtree, 0, {"checked", "true", STATE_CHECKED}, {0, 0, 0}, {0, 0, 0}},
{"grid", ROLE_TABLE, eTitleOnly, STATE_FOCUSABLE, {"readonly", 0, STATE_READONLY}, {"multiselect", 0, STATE_EXTSELECTABLE | STATE_MULTISELECTABLE}, {0, 0, 0}},
{"gridcell", ROLE_CELL, eAggregateSubtree, STATE_SELECTABLE, {"selected", 0, STATE_SELECTED}, {0, 0, 0}, {0, 0, 0}},
{"gridcell", ROLE_CELL, eAggregateSubtree, STATE_SELECTABLE, {"selected", 0, STATE_SELECTED}, {"readonly", 0, STATE_READONLY}, {0, 0, 0}},
{"option", ROLE_LISTITEM, eAggregateSubtree, STATE_SELECTABLE, {"selected", 0, STATE_SELECTED}, {0, 0, 0}, {0, 0, 0}},
{"progress-meter", ROLE_PROGRESSBAR, eTitleOnly, STATE_READONLY, {"valuenow", "unknown", STATE_MIXED}, {0, 0, 0}, {0, 0, 0}},
{"rowheader", ROLE_ROWHEADER, eAggregateSubtree, STATE_SELECTABLE, {"selected", 0, STATE_SELECTED}, {0, 0, 0}, {0, 0, 0}},
{"rowheader", ROLE_ROWHEADER, eAggregateSubtree, STATE_SELECTABLE, {"selected", 0, STATE_SELECTED}, {"readonly", 0, STATE_READONLY}, {0, 0, 0}},
{"secret-text", ROLE_PASSWORD_TEXT, eTitleOnly, STATE_PROTECTED, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, // XXX Use ext state STATE_SINGLE_LINE
{"select", ROLE_LIST, eTitleOnly, 0, {"readonly", 0, STATE_READONLY}, {"multiselect", 0, STATE_EXTSELECTABLE | STATE_MULTISELECTABLE}, {0, 0, 0}},
{"slider", ROLE_SLIDER, eTitleOnly, 0, {"readonly", 0, STATE_READONLY}, {0, 0, 0}, {0, 0, 0}},

View File

@ -105,11 +105,13 @@ class nsDocAccessible : public nsBlockAccessible,
NS_IMETHOD Shutdown();
NS_IMETHOD Init();
// nsPIAccessNode
NS_IMETHOD_(nsIFrame *) GetFrame(void);
protected:
enum EBusyState {eBusyStateUninitialized, eBusyStateLoading, eBusyStateDone};
virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
virtual nsIFrame* GetFrame();
virtual nsresult AddEventListeners();
virtual nsresult RemoveEventListeners();
void AddScrollListener();

View File

@ -47,10 +47,15 @@ class nsHTMLLinkAccessible : public nsLinkableAccessible
public:
nsHTMLLinkAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell, nsIFrame *aFrame);
// nsIAccessible
NS_IMETHOD GetName(nsAString& _retval);
NS_IMETHOD GetRole(PRUint32 *_retval);
NS_IMETHOD GetState(PRUint32 *_retval);
nsIFrame *GetFrame();
// nsPIAccessNode
NS_IMETHOD_(nsIFrame *) GetFrame(void);
private:
nsIFrame *mFrame;
};

View File

@ -48,9 +48,14 @@ class nsHTMLTextAccessible : public nsTextAccessibleWrap
{
public:
nsHTMLTextAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell, nsIFrame *aFrame);
nsIFrame* GetFrame();
// nsIAccessible
NS_IMETHOD GetName(nsAString& _retval);
NS_IMETHOD GetState(PRUint32 *aState);
// nsPIAccessNode
NS_IMETHOD_(nsIFrame *) GetFrame(void);
private:
nsIFrame *mFrame; // Only valid if node is not shut down (mWeakShell != null)
};

View File

@ -42,10 +42,12 @@
#include "nsIAccessibleWin32Object.h"
#include "nsArray.h"
#include "nsIDOMDocument.h"
#include "nsIFrame.h"
#include "nsINameSpaceManager.h"
#include "nsINodeInfo.h"
#include "nsIPrefService.h"
#include "nsIServiceManager.h"
#include "nsINameSpaceManager.h"
#include "nsIView.h"
// for the COM IEnumVARIANT solution in get_AccSelection()
#define _ATLBASE_IMPL
@ -167,15 +169,30 @@ STDMETHODIMP nsAccessibleWrap::get_accParent( IDispatch __RPC_FAR *__RPC_FAR *pp
if (!mWeakShell)
return E_FAIL; // We've been shut down
nsIFrame *frame = GetFrame();
nsCOMPtr<nsIAccessible> xpParentAccessible;
GetParent(getter_AddRefs(xpParentAccessible));
if (xpParentAccessible) {
*ppdispParent = NativeAccessible(xpParentAccessible);
return S_OK;
nsCOMPtr<nsPIAccessNode> parentAccessNode(do_QueryInterface(xpParentAccessible));
nsIFrame *parentFrame;
if (!frame || !parentAccessNode ||
((parentFrame = parentAccessNode->GetFrame()) != nsnull) && (frame->GetWindow() != parentFrame->GetWindow())) {
// This code is essentially our implementation of WindowFromAccessibleObject,
// because MSAA iterates get_accParent() until it sees an object of ROLE_WINDOW
// to know where the window for a given accessible is. We must expose the native
// window accessible that MSAA creates for us. This must be done for the document
// object as well as any layout that creates its own window (e.g. via overflow: scroll)
HWND hWnd = (HWND)frame->GetWindow()->GetNativeData(NS_NATIVE_WINDOW);
NS_ASSERTION(hWnd, "No window handle for window");
if (SUCCEEDED(AccessibleObjectFromWindow(hWnd, OBJID_WINDOW, IID_IAccessible,
(void**)ppdispParent))) {
return S_OK;
}
}
return E_FAIL;
NS_ASSERTION(xpParentAccessible, "No parent accessible where we're not direct child of window");
*ppdispParent = NativeAccessible(xpParentAccessible);
return S_OK;
}
STDMETHODIMP nsAccessibleWrap::get_accChildCount( long __RPC_FAR *pcountChildren)

View File

@ -43,6 +43,7 @@
#include "nsIDOMDocumentTraversal.h"
#include "nsIDOMNodeFilter.h"
#include "nsIDOMTreeWalker.h"
#include "nsIFrame.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIPresShell.h"
#include "nsISelectionController.h"
@ -161,38 +162,6 @@ STDMETHODIMP nsDocAccessibleWrap::get_accChild(
return nsAccessibleWrap::get_accChild(varChild, ppdispChild);
}
STDMETHODIMP nsDocAccessibleWrap::get_accParent( IDispatch __RPC_FAR *__RPC_FAR *ppdispParent)
{
// MSAA expects that client area accessibles return the native accessible for
// their containing window, otherwise WindowFromAccessibleObject() doesn't work.
void* wnd;
GetWindowHandle(&wnd);
HWND pWnd = ::GetParent(NS_REINTERPRET_CAST(HWND, wnd));
if (pWnd) {
// get the accessible.
void* ptr = nsnull;
#ifdef DEBUG_aleventhal
printf("* Ready to call AccessibleObjectFromWindow()\n");
#endif
HRESULT result = AccessibleObjectFromWindow(pWnd, OBJID_WINDOW, IID_IAccessible, &ptr);
#ifdef DEBUG_aleventhal
printf("* Successfully called AccessibleObjectFromWindow()\n");
#endif
if (SUCCEEDED(result)) {
IAccessible* msaaParentAccessible = (IAccessible*)ptr;
// got one? return it.
if (msaaParentAccessible) {
*ppdispParent = msaaParentAccessible;
return S_OK;
}
}
}
return E_FAIL;
}
NS_IMETHODIMP nsDocAccessibleWrap::FireToolkitEvent(PRUint32 aEvent, nsIAccessible* aAccessible, void* aData)
{
if (!mWeakShell) { // Means we're not active
@ -229,10 +198,19 @@ NS_IMETHODIMP nsDocAccessibleWrap::FireToolkitEvent(PRUint32 aEvent, nsIAccessib
// Clear out the cache in this subtree
}
HWND hWnd = NS_REINTERPRET_CAST(HWND, mWnd);
nsCOMPtr<nsPIAccessNode> privateAccessNode =
do_QueryInterface(aAccessible);
nsIFrame *frame = privateAccessNode->GetFrame();
// notify the window system
NotifyWinEvent(aEvent, hWnd, worldID, childID);
HWND hWnd = frame ? (HWND)frame->GetWindow()->GetNativeData(NS_NATIVE_WINDOW) :
(HWND)mWnd;
// Gecko uses two windows for every scrollable area. One window contains
// scrollbars and the child window contains only the client area.
// Details of the 2 window system:
// * Scrollbar window: caret drawing window & return value for WindowFromAccessibleObject()
// * Client area window: text drawing window & MSAA event window
NotifyWinEvent(aEvent, hWnd, worldID, childID); // Fire MSAA event for client area window
return NS_OK;
}

View File

@ -88,12 +88,6 @@ public:
/* [in] */ VARIANT varChild,
/* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild);
// Override get_accParent so that native accessible for window is
// returned as parent, otherwise WindowFromAccessibleObject() doesn't work.
// Also necessary for MSAA SDK's accexplore.exe testing tool to work.
virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_accParent(
/* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispParent);
NS_IMETHOD FireToolkitEvent(PRUint32 aEvent, nsIAccessible* aAccessible, void* aData);
NS_IMETHOD OnLocationChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, nsIURI *location);