Commit 91b40308 authored by aaronleventhal%moonset.net's avatar aaronleventhal%moonset.net
Browse files

Bug 341462. XUL menuitems should not fire accessible focus for mouseover....

Bug 341462. XUL menuitems should not fire accessible focus for mouseover. Patch by Ginn Chen. r=aaronlev
parent ffa95dbe
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -425,16 +425,11 @@ NS_IMETHODIMP nsDocAccessibleWrap::FireToolkitEvent(PRUint32 aEvent,
         */
    case nsIAccessibleEvent::EVENT_MENUSTART:
        MAI_LOG_DEBUG(("\n\nReceived: EVENT_MENUSTART\n"));
        atk_focus_tracker_notify(accWrap->GetAtkObject());
        g_signal_emit_by_name(accWrap->GetAtkObject(),
                              "selection_changed");
        rv = NS_OK;
        break;

    case nsIAccessibleEvent::EVENT_MENUEND:
        MAI_LOG_DEBUG(("\n\nReceived: EVENT_MENUEND\n"));
        g_signal_emit_by_name(accWrap->GetAtkObject(),
                              "selection_changed");
        rv = NS_OK;
        break;

+40 −30
Original line number Diff line number Diff line
@@ -417,10 +417,12 @@ void nsRootAccessible::FireAccessibleFocusEvent(nsIAccessible *aAccessible,
      // stays outside on that binding parent.
      nsCOMPtr<nsIDOMEventTarget> domEventTarget;
      nsevent->GetOriginalTarget(getter_AddRefs(domEventTarget));
      nsCOMPtr<nsIDOMNode> realFocusedNode = do_QueryInterface(domEventTarget);
      nsCOMPtr<nsIDOMNode> realFocusedNode(do_QueryInterface(domEventTarget));
      if (realFocusedNode) {
        mCaretAccessible->AttachNewSelectionListener(realFocusedNode);
      }
    }
  }

  // Fire focus only if it changes, but always fire focus events when aForceEvent == PR_TRUE
  if (gLastFocusedNode == aNode && !aForceEvent) {
@@ -498,7 +500,7 @@ void nsRootAccessible::FireCurrentFocusEvent()
                                                     NS_LITERAL_STRING("Events"),
                                                     getter_AddRefs(event))) &&
        NS_SUCCEEDED(event->InitEvent(NS_LITERAL_STRING("focus"), PR_TRUE, PR_TRUE))) {
      HandleEvent(event);
      HandleEventWithTarget(event, focusedNode);
    }
  }
}
@@ -515,6 +517,12 @@ NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
  if (!targetNode)
    return NS_ERROR_FAILURE;
  
  return HandleEventWithTarget(aEvent, targetNode);
}

NS_IMETHODIMP nsRootAccessible::HandleEventWithTarget(nsIDOMEvent* aEvent,
                                              nsCOMPtr<nsIDOMNode> targetNode)
{
  nsAutoString eventType;
  aEvent->GetType(eventType);
  nsAutoString localName;
@@ -656,25 +664,7 @@ NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
  }
  else 
#endif
  if (eventType.LowerCaseEqualsLiteral("dommenuitemactive")) {
    nsCOMPtr<nsIAccessible> containerAccessible = accessible;
    PRUint32 containerState = 0;
    do {
      nsIAccessible *tempAccessible = containerAccessible;
      tempAccessible->GetParent(getter_AddRefs(containerAccessible));
      if (!containerAccessible) {
        break;
      }
      containerAccessible->GetFinalState(&containerState);
    }
    while ((containerState & STATE_HASPOPUP) == 0);

    // Only fire focus event for DOMMenuItemActive is not inside collapsed popup
    if (0 == (containerState & STATE_COLLAPSED)) {
      FireAccessibleFocusEvent(accessible, targetNode, aEvent, PR_TRUE);
    }
  }
  else if (eventType.LowerCaseEqualsLiteral("focus")) {
  if (eventType.LowerCaseEqualsLiteral("focus")) {
    nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
      do_QueryInterface(targetNode);
    // Send focus to individual radio button or selected item
@@ -739,12 +729,6 @@ NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
      FireAccessibleFocusEvent(accessible, targetNode, aEvent);
    }
  }
  else if (eventType.LowerCaseEqualsLiteral("dommenubaractive"))
    privAcc->FireToolkitEvent(nsIAccessibleEvent::EVENT_MENUSTART, accessible, nsnull);
  else if (eventType.LowerCaseEqualsLiteral("dommenubarinactive")) {
    privAcc->FireToolkitEvent(nsIAccessibleEvent::EVENT_MENUEND, accessible, nsnull);
    FireCurrentFocusEvent();
  }
  else if (eventType.LowerCaseEqualsLiteral("popuphiding")) {
    // If accessible focus was inside popup that closes,
    // then restore it to true current focus.
@@ -770,8 +754,7 @@ NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
  }
#else
  AtkStateChange stateData;
  if (eventType.LowerCaseEqualsLiteral("focus") || 
           eventType.LowerCaseEqualsLiteral("dommenuitemactive")) {
  if (eventType.LowerCaseEqualsLiteral("focus")) {
    if (treeItemAccessible) { // use focused treeitem
      privAcc = do_QueryInterface(treeItemAccessible);
      privAcc->FireToolkitEvent(nsIAccessibleEvent::EVENT_FOCUS, 
@@ -863,6 +846,33 @@ NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
    //FireAccessibleFocusEvent(accessible, targetNode);  // Not yet used in ATK
  }
#endif
  else if (eventType.LowerCaseEqualsLiteral("dommenuitemactive")) {
    nsCOMPtr<nsIAccessible> containerAccessible;
    accessible->GetParent(getter_AddRefs(containerAccessible));
    NS_ENSURE_TRUE(containerAccessible, NS_OK);
    if (Role(containerAccessible) == ROLE_MENUBAR) {
      // It is top level menuitem
      // Only fire focus event if it is not collapsed
      if (State(accessible) & STATE_COLLAPSED)
        return NS_OK;
    }
    else {
      // It is not top level menuitem
      // Only fire focus event if it is not inside collapsed popup
      if (State(containerAccessible) & STATE_COLLAPSED)
        return NS_OK;
    }
    FireAccessibleFocusEvent(accessible, targetNode, aEvent, PR_TRUE);
  }
  else if (eventType.LowerCaseEqualsLiteral("dommenubaractive")) {
    privAcc->FireToolkitEvent(nsIAccessibleEvent::EVENT_MENUSTART,
                              accessible, nsnull);
  }
  else if (eventType.LowerCaseEqualsLiteral("dommenubarinactive")) {
    privAcc->FireToolkitEvent(nsIAccessibleEvent::EVENT_MENUEND,
                              accessible, nsnull);
    FireCurrentFocusEvent();
  }
  return NS_OK;
}

+2 −0
Original line number Diff line number Diff line
@@ -90,6 +90,8 @@ class nsRootAccessible : public nsDocAccessibleWrap,

  private:
    nsCOMPtr<nsITimer> mFireFocusTimer;
    NS_IMETHOD HandleEventWithTarget(nsIDOMEvent* aEvent, 
                             nsCOMPtr<nsIDOMNode> aTargetNode);
    static void FireFocusCallback(nsITimer *aTimer, void *aClosure);
    
  protected:
+8 −8
Original line number Diff line number Diff line
@@ -72,8 +72,12 @@ NS_IMETHODIMP nsXULMenuitemAccessible::GetState(PRUint32 *_retval)
  // Has Popup?
  nsAutoString tagName;
  element->GetLocalName(tagName);
  if (tagName.EqualsLiteral("menu"))
  if (tagName.EqualsLiteral("menu")) {
    *_retval |= STATE_HASPOPUP;
    PRBool isOpen;
    element->HasAttribute(NS_LITERAL_STRING("open"), &isOpen);
    *_retval |= isOpen ? STATE_EXPANDED : STATE_COLLAPSED;
  }

  nsAutoString menuItemType;
  element->GetAttribute(NS_LITERAL_STRING("type"), menuItemType); 
@@ -95,15 +99,11 @@ NS_IMETHODIMP nsXULMenuitemAccessible::GetState(PRUint32 *_retval)
  // Offscreen?
  // If parent or grandparent menuitem is offscreen, then we're offscreen too
  // We get it by replacing the current offscreen bit with the parent's
  PRUint32 parentState = 0;
  nsCOMPtr<nsIAccessible> parentAccessible;
  if (parentAccessible) {
  GetParent(getter_AddRefs(parentAccessible));
  if (parentAccessible) {
      parentAccessible->GetFinalState(&parentState);
    *_retval &= ~STATE_OFFSCREEN;  // clear the old OFFSCREEN bit
      *_retval |= (parentState & STATE_OFFSCREEN);  // or it with the parent's offscreen bit
    }
    *_retval |= (State(parentAccessible) & STATE_OFFSCREEN);  // or it with the parent's offscreen bit
  }

  return NS_OK;
+1 −0
Original line number Diff line number Diff line
@@ -727,6 +727,7 @@ nsMenuFrame::OpenMenu(PRBool aActivateFlag)
    MarkAsGenerated();

    mContent->SetAttr(kNameSpaceID_None, nsXULAtoms::open, NS_LITERAL_STRING("true"), PR_TRUE);
    FireDOMEventSynch(NS_LITERAL_STRING("DOMMenuItemActive"));
  }
  else mContent->UnsetAttr(kNameSpaceID_None, nsXULAtoms::open, PR_TRUE);
  OpenMenuInternal(aActivateFlag);