From 228c15696a6149a5265534dda96ebf25fe8d0fe5 Mon Sep 17 00:00:00 2001 From: "aaronl%netscape.com" Date: Fri, 25 Oct 2002 00:31:23 +0000 Subject: [PATCH] Bug 141880. Always report same hwnd for MSAA focus events as the hwnd for the current system focus. r=jgaunt, sr=bryner, a=roc+moz. Bug 174796. XUL browser's MSAA cache not working correctly. r=jgaunt, sr=bryner, a=roc+moz git-svn-id: svn://10.0.0.236/trunk@132486 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/widget/src/windows/Accessible.cpp | 122 +++++++++++++++------- mozilla/widget/src/windows/Accessible.h | 12 ++- 2 files changed, 92 insertions(+), 42 deletions(-) diff --git a/mozilla/widget/src/windows/Accessible.cpp b/mozilla/widget/src/windows/Accessible.cpp index 741f3adc325..5aa7d8d49be 100644 --- a/mozilla/widget/src/windows/Accessible.cpp +++ b/mozilla/widget/src/windows/Accessible.cpp @@ -43,6 +43,9 @@ #include "nsIAccessibleWin32Object.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" +#include "nsIPresShell.h" +#include "nsIDocument.h" +#include "nsIViewManager.h" #include "nsIDOMDocumentType.h" #include "nsINameSpaceManager.h" #include "nsITextContent.h" @@ -51,6 +54,8 @@ #include "nsReadableUtils.h" #include "nsWindow.h" #include "String.h" +#include "nsIPref.h" +#include "nsIServiceManager.h" // for the COM IEnumVARIANT solution in get_AccSelection() #define _ATLBASE_IMPL @@ -69,6 +74,16 @@ extern CComModule _Module; static gAccessibles = 0; #endif +CComModule _Module; + +static NS_DEFINE_CID(kPrefCID, NS_PREF_CID); + +PRInt32 RootAccessible::gListCount = 0; +PRInt32 RootAccessible::gNextPos = 0; +nsAccessibleEventMap RootAccessible::gList[MAX_LIST_SIZE]; +PRBool Accessible::gIsCacheDisabled = PR_FALSE; +PRBool Accessible::gIsEnumVariantSupportDisabled = PR_FALSE; + // {61044601-A811-4e2b-BBBA-17BFABD329D7} EXTERN_C GUID CDECL CLSID_Accessible = { 0x61044601, 0xa811, 0x4e2b, { 0xbb, 0xba, 0x17, 0xbf, 0xab, 0xd3, 0x29, 0xd7 } }; @@ -77,8 +92,6 @@ EXTERN_C GUID CDECL CLSID_Accessible = * Class Accessible */ -CComModule _Module; - //----------------------------------------------------- // construction //----------------------------------------------------- @@ -128,7 +141,7 @@ STDMETHODIMP Accessible::QueryInterface(REFIID iid, void** ppv) if (IID_IUnknown == iid || IID_IDispatch == iid || IID_IAccessible == iid) *ppv = NS_STATIC_CAST(IAccessible*, this); - else if (IID_IEnumVARIANT == iid) { + else if (IID_IEnumVARIANT == iid && !gIsEnumVariantSupportDisabled) { CacheMSAAChildren(); if (mCachedChildCount > 0) // Don't support this interface for leaf elements *ppv = NS_STATIC_CAST(IEnumVARIANT*, this); @@ -620,6 +633,8 @@ Accessible::GetCachedChild(long aChildNum) void Accessible::CacheMSAAChildren() { + if (gIsCacheDisabled) + mCachedChildCount = -1; // Don't use old info if (mCachedChildCount < 0) GetCachedChild(-1); // This caches the children and sets mCachedChildCount } @@ -641,7 +656,8 @@ STDMETHODIMP Accessible::accNavigate( xpAccessibleStart->AccNavigateDown(getter_AddRefs(xpAccessibleResult)); break; case NAVDIR_FIRSTCHILD: - if (mCachedChildCount == -1 || xpAccessibleStart != mXPAccessible) { + if (mCachedChildCount == -1 || xpAccessibleStart != mXPAccessible || + gIsCacheDisabled) { xpAccessibleStart->GetAccFirstChild(getter_AddRefs(xpAccessibleResult)); } else if (mCachedFirstChild) { @@ -655,12 +671,12 @@ STDMETHODIMP Accessible::accNavigate( xpAccessibleStart->AccNavigateLeft(getter_AddRefs(xpAccessibleResult)); break; case NAVDIR_NEXT: - if (isNavigatingFromSelf && mCachedNextSibling) { + if (isNavigatingFromSelf && mCachedNextSibling && !gIsCacheDisabled) { msaaAccessible = mCachedNextSibling; } else if (!mFlagBits.mIsLastSibling) { xpAccessibleStart->GetAccNextSibling(getter_AddRefs(xpAccessibleResult)); - if (!xpAccessibleResult && isNavigatingFromSelf) + if (!xpAccessibleResult && isNavigatingFromSelf && !gIsCacheDisabled) mFlagBits.mIsLastSibling = PR_TRUE; } break; @@ -681,14 +697,18 @@ STDMETHODIMP Accessible::accNavigate( if (navDir == NAVDIR_NEXT) { if (mCachedNextSibling) mCachedNextSibling->Release(); - mCachedNextSibling = msaaAccessible; - msaaAccessible->AddRef(); // addref for the caching + if (!gIsCacheDisabled) { + mCachedNextSibling = msaaAccessible; + msaaAccessible->AddRef(); // addref for the caching + } } if (navDir == NAVDIR_FIRSTCHILD) { if (mCachedFirstChild) mCachedFirstChild->Release(); - mCachedFirstChild = msaaAccessible; - msaaAccessible->AddRef(); // addref for the caching + if (!gIsCacheDisabled) { + mCachedFirstChild = msaaAccessible; + msaaAccessible->AddRef(); // addref for the caching + } } } } @@ -797,18 +817,19 @@ Accessible::Next(ULONG aNumElementsRequested, VARIANT FAR* pvar, ULONG FAR* aNum accNavigate(NAVDIR_FIRSTCHILD, varStart, &pvar[0]); for (long childIndex = 0; pvar[*aNumElementsFetched].vt == VT_DISPATCH; ++childIndex) { - IAccessible *msaaAccessible = NS_STATIC_CAST(IAccessible*, pvar[*aNumElementsFetched].pdispVal); + PRBool wasAccessibleFetched = PR_FALSE; + Accessible *msaaAccessible = NS_STATIC_CAST(Accessible*, pvar[*aNumElementsFetched].pdispVal); if (childIndex >= mEnumVARIANTPosition) { if (++*aNumElementsFetched >= aNumElementsRequested) break; - } - else { - msaaAccessible->Release(); // this accessible will not be received by the caller + wasAccessibleFetched = PR_TRUE; } msaaAccessible->accNavigate(NAVDIR_NEXT, varStart, &pvar[*aNumElementsFetched] ); + if (!wasAccessibleFetched) + msaaAccessible->Release(); // this accessible will not be received by the caller } - mEnumVARIANTPosition = childIndex; + mEnumVARIANTPosition += *aNumElementsFetched; return NOERROR; } @@ -1089,12 +1110,20 @@ RootAccessible::Release(void) RootAccessible::RootAccessible(nsIAccessible* aAcc, HWND aWnd):DocAccessible(aAcc,nsnull,aWnd) { - mListCount = 0; - mNextPos = 0; - nsCOMPtr r(do_QueryInterface(mXPAccessible)); if (r) r->AddAccessibleEventListener(this); + + static PRBool prefsInitialized; + + if (!prefsInitialized) { + nsCOMPtr prefService(do_GetService(kPrefCID)); + if (prefService) { + prefService->GetBoolPref("accessibility.disablecache", &Accessible::gIsCacheDisabled); + prefService->GetBoolPref("accessibility.disableenumvariant", &Accessible::gIsEnumVariantSupportDisabled); + } + prefsInitialized = PR_TRUE; + } } RootAccessible::~RootAccessible() @@ -1104,8 +1133,8 @@ RootAccessible::~RootAccessible() r->RemoveAccessibleEventListener(); // free up accessibles - for (int i=0; i < mListCount; i++) - mList[i].mAccessible = nsnull; + for (int i=0; i < gListCount; i++) + gList[i].mAccessible = nsnull; } void RootAccessible::GetNSAccessibleFor(VARIANT varChild, nsCOMPtr& aAcc) @@ -1123,13 +1152,14 @@ void RootAccessible::GetNSAccessibleFor(VARIANT varChild, nsCOMPtrGetAccRole(&role)) && role == ROLE_SYSTEM_CARET) { childID = CHILDID_SELF; @@ -1186,13 +1216,31 @@ NS_IMETHODIMP RootAccessible::HandleEvent(PRUint32 aEvent, nsIAccessible* aAcces else childID = GetIdFor(aAccessible); // get the id for the accessible + if (role == ROLE_SYSTEM_PANE && aEvent == EVENT_STATE_CHANGE) { + // Something on the document has changed + // Clear out the cache in this subtree + if (mCachedFirstChild) { + mCachedFirstChild->Release(); + mCachedFirstChild = nsnull; + } + mCachedChildCount = -1; + } + + HWND hWnd = mWnd; + if (aEvent == EVENT_FOCUS) { + GUITHREADINFO guiInfo; + if (!::GetGUIThreadInfo(NULL, &guiInfo)) + return NS_OK; + hWnd = guiInfo.hwndFocus; + } + // notify the window system - NotifyWinEvent(aEvent, mWnd, worldID, childID); + NotifyWinEvent(aEvent, hWnd, worldID, childID); return NS_OK; } -PRInt32 RootAccessible::GetIdFor(nsIAccessible* aAccessible) +PRUint32 RootAccessible::GetIdFor(nsIAccessible* aAccessible) { // A child ID of the window is required, when we use NotifyWinEvent, so that the 3rd party application // can call back and get the IAccessible the event occured on. @@ -1201,21 +1249,21 @@ PRInt32 RootAccessible::GetIdFor(nsIAccessible* aAccessible) PRInt32 uniqueID; aAccessible->GetAccId(&uniqueID); - for (PRInt32 index = 0; index < mListCount; index++) - if (uniqueID == mList[index].mId) { + for (PRInt32 index = 0; index < gListCount; index++) + if (uniqueID == gList[index].mId) { // Change old ID in list to use most recent accessible, // rather than create multiple entries for same accessible - mList[index].mAccessible = aAccessible; + gList[index].mAccessible = aAccessible; return uniqueID; } - mList[mNextPos].mId = uniqueID; - mList[mNextPos].mAccessible = aAccessible; + gList[gNextPos].mId = uniqueID; + gList[gNextPos].mAccessible = aAccessible; - if (++mNextPos >= MAX_LIST_SIZE) - mNextPos = 0; - if (mListCount < MAX_LIST_SIZE) - mListCount++; + if (++gNextPos >= MAX_LIST_SIZE) + gNextPos = 0; + if (gListCount < MAX_LIST_SIZE) + gListCount++; return uniqueID; } diff --git a/mozilla/widget/src/windows/Accessible.h b/mozilla/widget/src/windows/Accessible.h index e5305d47637..9bd32a21cc6 100644 --- a/mozilla/widget/src/windows/Accessible.h +++ b/mozilla/widget/src/windows/Accessible.h @@ -220,6 +220,8 @@ protected: // This is what most assistive tech tends to do, so it shouldn't be a problem. void CacheMSAAChildren(); IAccessible *GetCachedChild(long aChildNum); + static PRBool gIsCacheDisabled; + static PRBool gIsEnumVariantSupportDisabled; private: /// the accessible library and cached methods @@ -292,15 +294,15 @@ public: // nsIAccessibleEventListener NS_DECL_NSIACCESSIBLEEVENTLISTENER - PRInt32 GetIdFor(nsIAccessible* aAccessible); + PRUint32 GetIdFor(nsIAccessible* aAccessible); virtual void GetNSAccessibleFor(VARIANT varChild, nsCOMPtr& aAcc); -private: + private: // list of accessible that may have had // events fire. - nsAccessibleEventMap mList[MAX_LIST_SIZE]; - PRInt32 mListCount; - PRInt32 mNextPos; + static nsAccessibleEventMap gList[MAX_LIST_SIZE]; + static PRInt32 gListCount; + static PRInt32 gNextPos; }; #endif