Bug 377644. Move MSAA event firing to accessible wrap, to fix missing events. Patch by Alexander Surkov. r=aaronlev
authoraaronleventhal@moonset.net
Mon, 16 Apr 2007 13:23:00 -0700
changeset 563 6eb9346e61a01328d732d04bd6b829be6c8c5431
parent 562 8b101a22b0f6da5a45d69915c831b5bef3bd7bf4
child 564 093fd63f120523ff3218e095f64b339cd9a46f6e
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaaronlev
bugs377644
milestone1.9a4pre
Bug 377644. Move MSAA event firing to accessible wrap, to fix missing events. Patch by Alexander Surkov. r=aaronlev
accessible/src/msaa/nsAccessibleWrap.cpp
accessible/src/msaa/nsAccessibleWrap.h
accessible/src/msaa/nsDocAccessibleWrap.cpp
accessible/src/msaa/nsDocAccessibleWrap.h
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -33,17 +33,20 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsAccessibleWrap.h"
 #include "nsAccessibilityAtoms.h"
+
+#include "nsIAccessibleDocument.h"
 #include "nsIAccessibleSelectable.h"
+#include "nsIAccessibleEvent.h"
 #include "nsIAccessibleWin32Object.h"
 
 #include "Accessible2_i.c"
 #include "AccessibleAction_i.c"
 #include "AccessibleStates.h"
 
 #include "nsIMutableArray.h"
 #include "nsIDOMDocument.h"
@@ -51,16 +54,17 @@
 #include "nsIScrollableFrame.h"
 #include "nsINameSpaceManager.h"
 #include "nsINodeInfo.h"
 #include "nsIPrefService.h"
 #include "nsIServiceManager.h"
 #include "nsTextFormatter.h"
 #include "nsIView.h"
 #include "nsRoleMap.h"
+#include "nsEventMap.h"
 #include "nsArrayUtils.h"
 
 /* For documentation of the accessibility architecture,
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
 //#define DEBUG_LEAKS
 
@@ -1401,19 +1405,125 @@ STDMETHODIMP nsAccessibleWrap::Invoke(DI
 
 NS_IMETHODIMP nsAccessibleWrap::GetNativeInterface(void **aOutAccessible)
 {
   *aOutAccessible = NS_STATIC_CAST(IAccessible*, this);
   NS_ADDREF_THIS();
   return NS_OK;
 }
 
+// nsPIAccessible
+
+NS_IMETHODIMP
+nsAccessibleWrap::FireAccessibleEvent(nsIAccessibleEvent *aEvent)
+{
+  NS_ENSURE_ARG(aEvent);
+
+  nsresult rv = nsAccessible::FireAccessibleEvent(aEvent);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRUint32 eventType = 0;
+  aEvent->GetEventType(&eventType);
+
+  NS_ENSURE_TRUE(eventType > 0 &&
+                 eventType < nsIAccessibleEvent::EVENT_LAST_ENTRY,
+                 NS_ERROR_FAILURE);
+
+  PRUint32 winLastEntry = gWinEventMap[nsIAccessibleEvent::EVENT_LAST_ENTRY];
+  NS_ASSERTION(winLastEntry == kEVENT_LAST_ENTRY,
+               "MSAA event map skewed");
+
+  PRUint32 winEvent = gWinEventMap[eventType];
+  if (!winEvent)
+    return NS_OK;
+
+  // Means we're not active.
+  NS_ENSURE_TRUE(mWeakShell, NS_ERROR_FAILURE);
+
+  nsCOMPtr<nsIAccessible> accessible;
+  aEvent->GetAccessible(getter_AddRefs(accessible));
+  if (!accessible)
+    return NS_OK;
+
+  PRInt32 childID, worldID = OBJID_CLIENT;
+  PRUint32 role = ROLE_SYSTEM_TEXT; // Default value
+
+  nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(accessible));
+  NS_ENSURE_STATE(accessNode);
+
+  HWND hWnd = 0;
+
+  if (NS_SUCCEEDED(accessible->GetRole(&role)) && role == ROLE_SYSTEM_CARET) {
+    childID = CHILDID_SELF;
+    worldID = OBJID_CARET;
+  } else {
+    childID = GetChildIDFor(accessible); // get the id for the accessible
+    if (!childID)
+      return NS_OK; // Can't fire an event without a child ID
+
+    // See if we're in a scrollable area with its own window
+    nsCOMPtr<nsIAccessible> newAccessible;
+    if (eventType == nsIAccessibleEvent::EVENT_HIDE) {
+      // Don't use frame from current accessible when we're hiding that
+      // accessible.
+      accessible->GetParent(getter_AddRefs(newAccessible));
+    } else {
+      newAccessible = accessible;
+    }
+
+    nsCOMPtr<nsPIAccessNode> privateAccessNode =
+      do_QueryInterface(newAccessible);
+    if (privateAccessNode) {
+      nsIFrame *frame = privateAccessNode->GetFrame();
+      if (frame)
+        hWnd = (HWND)frame->GetWindow()->GetNativeData(NS_NATIVE_WINDOW);
+    }
+  }
+
+  if (!hWnd) {
+    void* handle = nsnull;
+    nsCOMPtr<nsIAccessibleDocument> accessibleDoc;
+    accessNode->GetAccessibleDocument(getter_AddRefs(accessibleDoc));
+    NS_ENSURE_STATE(accessibleDoc);
+    accessibleDoc->GetWindowHandle(&handle);
+    hWnd = (HWND)handle;
+  }
+
+  // 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
+
+  // Fire MSAA event for client area window.
+  NotifyWinEvent(winEvent, hWnd, worldID, childID);
+
+  return NS_OK;
+}
 
 //------- Helper methods ---------
 
+PRInt32 nsAccessibleWrap::GetChildIDFor(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.
+
+  void *uniqueID;
+  nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(aAccessible));
+  if (!accessNode) {
+    return 0;
+  }
+  accessNode->GetUniqueID(&uniqueID);
+
+  // Yes, this means we're only compatibible with 32 bit
+  // MSAA is only available for 32 bit windows, so it's okay
+  return - NS_PTR_TO_INT32(uniqueID);
+}
+
 IDispatch *nsAccessibleWrap::NativeAccessible(nsIAccessible *aXPAccessible)
 {
   nsCOMPtr<nsIAccessibleWin32Object> accObject(do_QueryInterface(aXPAccessible));
   if (accObject) {
     void* hwnd;
     accObject->GetHwnd(&hwnd);
     if (hwnd) {
       IDispatch *retval = nsnull;
--- a/accessible/src/msaa/nsAccessibleWrap.h
+++ b/accessible/src/msaa/nsAccessibleWrap.h
@@ -266,16 +266,22 @@ class nsAccessibleWrap : public nsAccess
   STDMETHODIMP GetTypeInfoCount(UINT *p);
   STDMETHODIMP GetTypeInfo(UINT i, LCID lcid, ITypeInfo **ppti);
   STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames,
                                UINT cNames, LCID lcid, DISPID *rgDispId);
   STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid,
         LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);
 
+  // nsPIAccessible
+  NS_IMETHOD FireAccessibleEvent(nsIAccessibleEvent *aEvent);
+
+  // Helper methods
+  static PRInt32 GetChildIDFor(nsIAccessible* aAccessible);
+
   virtual void GetXPAccessibleFor(const VARIANT& aVarChild, nsIAccessible **aXPAccessible);
   NS_IMETHOD GetNativeInterface(void **aOutAccessible);
 
   // NT4 does not have the oleacc that defines these methods. So we define copies here that automatically
   // load the library only if needed.
   static STDMETHODIMP AccessibleObjectFromWindow(HWND hwnd,DWORD dwObjectID,REFIID riid,void **ppvObject);
   static STDMETHODIMP NotifyWinEvent(DWORD event,HWND hwnd,LONG idObjectType,LONG idObject);
 
--- a/accessible/src/msaa/nsDocAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsDocAccessibleWrap.cpp
@@ -34,18 +34,16 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsDocAccessibleWrap.h"
 #include "ISimpleDOMDocument_i.c"
 #include "nsIAccessibilityService.h"
-#include "nsIAccessibleEvent.h"
-#include "nsEventMap.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeNode.h"
 #include "nsIFrame.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIPresShell.h"
 #include "nsISelectionController.h"
 #include "nsIServiceManager.h"
 #include "nsIURI.h"
@@ -161,111 +159,16 @@ STDMETHODIMP nsDocAccessibleWrap::get_ac
   return nsAccessibleWrap::get_accChild(varChild, ppdispChild);
 }
 
 NS_IMETHODIMP nsDocAccessibleWrap::Shutdown()
 {
   return nsDocAccessible::Shutdown();
 }
 
-NS_IMETHODIMP
-nsDocAccessibleWrap::FireToolkitEvent(PRUint32 aEvent, nsIAccessible* aAccessible, void* aData)
-{
-  NS_ENSURE_TRUE(aEvent > 0 && aEvent < nsIAccessibleEvent::EVENT_LAST_ENTRY,
-                 NS_ERROR_FAILURE);
-
-  NS_ASSERTION(gWinEventMap[nsIAccessibleEvent::EVENT_LAST_ENTRY] == kEVENT_LAST_ENTRY,
-               "MSAA event map skewed");
-
-  PRUint32 winEvent = gWinEventMap[aEvent];
-  if (!winEvent)
-    return NS_OK;
-
-  // Means we're not active.
-  NS_ENSURE_TRUE(mWeakShell, NS_ERROR_FAILURE);
-
-  nsDocAccessible::FireToolkitEvent(aEvent, aAccessible, aData); // Fire nsIObserver message
-
-#ifdef SWALLOW_DOC_FOCUS_EVENTS
-  // Remove this until we can figure out which focus events are coming at
-  // the same time as native window focus events, although
-  // perhaps 2 duplicate focus events on the window isn't really a problem
-  if (aEvent == nsIAccessibleEvent::EVENT_FOCUS) {
-    // Don't fire accessible focus event for documents, 
-    // Microsoft Windows will generate those from native window focus events
-    nsCOMPtr<nsIAccessibleDocument> accessibleDoc(do_QueryInterface(aAccessible));
-    if (accessibleDoc)
-      return NS_OK;
-  }
-#endif
-
-  PRInt32 childID, worldID = OBJID_CLIENT;
-  PRUint32 role = ROLE_SYSTEM_TEXT; // Default value
-
-  HWND hWnd = (HWND)mWnd;
-
-  if (NS_SUCCEEDED(aAccessible->GetRole(&role)) && role == ROLE_SYSTEM_CARET) {
-    childID = CHILDID_SELF;
-    worldID = OBJID_CARET;
-  }
-  else {
-    childID = GetChildIDFor(aAccessible); // get the id for the accessible
-    if (!childID) {
-      return NS_OK; // Can't fire an event without a child ID
-    }
-    if (aAccessible != this) {
-      // See if we're in a scrollable area with its own window
-      nsCOMPtr<nsIAccessible> accessible;
-      if (aEvent == nsIAccessibleEvent::EVENT_HIDE) {
-        // Don't use frame from current accessible when we're hiding that accessible
-        aAccessible->GetParent(getter_AddRefs(accessible));
-      }
-      else {
-        accessible = aAccessible;
-      }
-      nsCOMPtr<nsPIAccessNode> privateAccessNode =
-        do_QueryInterface(accessible);
-      if (privateAccessNode) {
-        nsIFrame *frame = privateAccessNode->GetFrame();
-        if (frame) {
-          hWnd = (HWND)frame->GetWindow()->GetNativeData(NS_NATIVE_WINDOW); 
-        }
-      }
-    }
-  }
-
-  // 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
-
-  // Fire MSAA event for client area window.
-  NotifyWinEvent(winEvent, hWnd, worldID, childID);
-
-  return NS_OK;
-}
-
-PRInt32 nsDocAccessibleWrap::GetChildIDFor(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.
-
-  void *uniqueID;
-  nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(aAccessible));
-  if (!accessNode) {
-    return 0;
-  }
-  accessNode->GetUniqueID(&uniqueID);
-
-  // Yes, this means we're only compatibible with 32 bit
-  // MSAA is only available for 32 bit windows, so it's okay
-  return - NS_PTR_TO_INT32(uniqueID);
-}
-
 NS_IMETHODIMP nsDocAccessibleWrap::FireAnchorJumpEvent()
 {
   // Staying on the same page, jumping to a named anchor
   // Fire EVENT_SCROLLING_START on first leaf accessible -- because some
   // assistive technologies only cache the child numbers for leaf accessibles
   // the can only relate events back to their internal model if it's a leaf.
   // There is usually an accessible for the focus node, but if it's an empty text node
   // we have to move forward in the document to get one
--- a/accessible/src/msaa/nsDocAccessibleWrap.h
+++ b/accessible/src/msaa/nsDocAccessibleWrap.h
@@ -54,18 +54,16 @@ public:
     nsDocAccessibleWrap(nsIDOMNode *aNode, nsIWeakReference *aShell);
     virtual ~nsDocAccessibleWrap();
 
     // IUnknown
     STDMETHODIMP_(ULONG) AddRef();
     STDMETHODIMP_(ULONG) Release();
     STDMETHODIMP      QueryInterface(REFIID, void**);
 
-    static PRInt32 GetChildIDFor(nsIAccessible* aAccessible);
-
     void GetXPAccessibleFor(const VARIANT& varChild, nsIAccessible **aXPAccessible);
 
     // ISimpleDOMDocument
     virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_URL( 
         /* [out] */ BSTR __RPC_FAR *url);
     
     virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_title( 
         /* [out] */ BSTR __RPC_FAR *title);
@@ -85,13 +83,12 @@ public:
 
     // IAccessible
     // Override get_accChild so that it can get any child via the unique ID
     virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_accChild( 
         /* [in] */ VARIANT varChild,
         /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild);
 
     NS_IMETHOD Shutdown();
-    NS_IMETHOD FireToolkitEvent(PRUint32 aEvent, nsIAccessible* aAccessible, void* aData);
     NS_IMETHOD FireAnchorJumpEvent();
 };
 
 #endif