Bug 889512 - no focus event for google's moving textbox, r=tbsaunde
authorAlexander Surkov <surkov.alexander@gmail.com>
Wed, 31 Jul 2013 10:47:39 -0400
changeset 140755 2e7ae68148a6c5fa6a5bc40be4f47479419e0ae2
parent 140754 e27bd873b413e11e3c197b3b07f79d79899d4d22
child 140756 e926c98528ffc3c7be844119bd5ddf9de72084ff
push id31853
push usersurkov.alexander@gmail.com
push dateWed, 31 Jul 2013 14:48:03 +0000
treeherdermozilla-inbound@2e7ae68148a6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstbsaunde
bugs889512
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 889512 - no focus event for google's moving textbox, r=tbsaunde
accessible/src/generic/DocAccessible.cpp
accessible/src/generic/DocAccessible.h
--- a/accessible/src/generic/DocAccessible.cpp
+++ b/accessible/src/generic/DocAccessible.cpp
@@ -1825,20 +1825,26 @@ DocAccessible::UpdateTree(Accessible* aC
 }
 
 uint32_t
 DocAccessible::UpdateTreeInternal(Accessible* aChild, bool aIsInsert,
                                   AccReorderEvent* aReorderEvent)
 {
   uint32_t updateFlags = eAccessible;
 
+  // If a focused node has been shown then it could mean its frame was recreated
+  // while the node stays focused and we need to fire focus event on
+  // the accessible we just created. If the queue contains a focus event for
+  // this node already then it will be suppressed by this one.
+  Accessible* focusedAcc = nullptr;
+
   nsINode* node = aChild->GetNode();
   if (aIsInsert) {
     // Create accessible tree for shown accessible.
-    CacheChildrenInSubtree(aChild);
+    CacheChildrenInSubtree(aChild, &focusedAcc);
 
   } else {
     // Fire menupopup end event before hide event if a menu goes away.
 
     // XXX: We don't look into children of hidden subtree to find hiding
     // menupopup (as we did prior bug 570275) because we don't do that when
     // menu is showing (and that's impossible until bug 606924 is fixed).
     // Nevertheless we should do this at least because layout coalesces
@@ -1865,57 +1871,59 @@ DocAccessible::UpdateTreeInternal(Access
       // Fire EVENT_MENUPOPUP_START if ARIA menu appears.
       FireDelayedEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START, aChild);
 
     } else if (ariaRole == roles::ALERT) {
       // Fire EVENT_ALERT if ARIA alert appears.
       updateFlags = eAlertAccessible;
       FireDelayedEvent(nsIAccessibleEvent::EVENT_ALERT, aChild);
     }
-
-    // If focused node has been shown then it means its frame was recreated
-    // while it's focused. Fire focus event on new focused accessible. If
-    // the queue contains focus event for this node then it's suppressed by
-    // this one.
-    // XXX: do we really want to send focus to focused DOM node not taking into
-    // account active item?
-    if (FocusMgr()->IsFocused(aChild))
-      FocusMgr()->DispatchFocusEvent(this, aChild);
-
   } else {
     // Update the tree for content removal.
     // The accessible parent may differ from container accessible if
     // the parent doesn't have own DOM node like list accessible for HTML
     // selects.
     Accessible* parent = aChild->Parent();
     NS_ASSERTION(parent, "No accessible parent?!");
     if (parent)
       parent->RemoveChild(aChild);
 
     UncacheChildrenInSubtree(aChild);
   }
 
+  // XXX: do we really want to send focus to focused DOM node not taking into
+  // account active item?
+  if (focusedAcc)
+    FocusMgr()->DispatchFocusEvent(this, focusedAcc);
+
   return updateFlags;
 }
 
 void
-DocAccessible::CacheChildrenInSubtree(Accessible* aRoot)
+DocAccessible::CacheChildrenInSubtree(Accessible* aRoot,
+                                      Accessible** aFocusedAcc)
 {
+  // If the accessible is focused then report a focus event after all related
+  // mutation events.
+  if (aFocusedAcc && !*aFocusedAcc &&
+      FocusMgr()->HasDOMFocus(aRoot->GetContent()))
+    *aFocusedAcc = aRoot;
+
   aRoot->EnsureChildren();
 
   // Make sure we create accessible tree defined in DOM only, i.e. if accessible
   // provides specific tree (like XUL trees) then tree creation is handled by
   // this accessible.
   uint32_t count = aRoot->ContentChildCount();
   for (uint32_t idx = 0; idx < count; idx++) {
     Accessible* child = aRoot->ContentChildAt(idx);
     NS_ASSERTION(child, "Illicit tree change while tree is created!");
     // Don't cross document boundaries.
     if (child && child->IsContent())
-      CacheChildrenInSubtree(child);
+      CacheChildrenInSubtree(child, aFocusedAcc);
   }
 
   // Fire document load complete on ARIA documents.
   // XXX: we should delay an event if the ARIA document has aria-busy.
   if (aRoot->HasARIARole() && !aRoot->IsDoc()) {
     a11y::role role = aRoot->ARIARole();
     if (role == roles::DIALOG || role == roles::DOCUMENT)
       FireDelayedEvent(nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE, aRoot);
--- a/accessible/src/generic/DocAccessible.h
+++ b/accessible/src/generic/DocAccessible.h
@@ -444,18 +444,23 @@ protected:
     eAlertAccessible = 2
   };
 
   uint32_t UpdateTreeInternal(Accessible* aChild, bool aIsInsert,
                               AccReorderEvent* aReorderEvent);
 
   /**
    * Create accessible tree.
+   *
+   * @param aRoot       [in] a root of subtree to create
+   * @param aFocusedAcc [in, optional] a focused accessible under created
+   *                      subtree if any
    */
-  void CacheChildrenInSubtree(Accessible* aRoot);
+  void CacheChildrenInSubtree(Accessible* aRoot,
+                              Accessible** aFocusedAcc = nullptr);
 
   /**
    * Remove accessibles in subtree from node to accessible map.
    */
   void UncacheChildrenInSubtree(Accessible* aRoot);
 
   /**
    * Shutdown any cached accessible in the subtree.