mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
Bug 283482. MSAA events and objects in wrong HWND for CSS overflow children. r=bz, sr=roc
This commit is contained in:
parent
81cd248f48
commit
d6b4a62ca7
@ -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();
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -125,7 +125,6 @@ protected:
|
||||
already_AddRefed<nsIPresShell> GetPresShell();
|
||||
nsPresContext* GetPresContext();
|
||||
already_AddRefed<nsIAccessibleDocument> GetDocAccessible();
|
||||
virtual nsIFrame* GetFrame();
|
||||
|
||||
nsCOMPtr<nsIDOMNode> mDOMNode;
|
||||
nsCOMPtr<nsIWeakReference> mWeakShell;
|
||||
|
@ -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}},
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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)
|
||||
};
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user