Bug 1168042, return a bool from PerformAccessKey indicating if focus was changed, r=masayuki
authorNeil Deakin <neil@mozilla.com>
Fri, 18 Sep 2015 08:18:42 -0400
changeset 295833 b3a9162ec47badf22c806d758c8c3fc075663dda
parent 295832 07853d7b87c1ab9c8e210b096aa24790252a92bb
child 295834 30333d9cbcb9aaa4c38e92cb3a299bc81954fe6a
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki
bugs1168042
milestone43.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 1168042, return a bool from PerformAccessKey indicating if focus was changed, r=masayuki
dom/base/nsIContent.h
dom/html/HTMLLabelElement.cpp
dom/html/HTMLLabelElement.h
dom/html/HTMLLegendElement.cpp
dom/html/HTMLLegendElement.h
dom/html/nsGenericHTMLElement.cpp
dom/html/nsGenericHTMLElement.h
dom/xul/nsXULElement.cpp
dom/xul/nsXULElement.h
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -35,18 +35,18 @@ struct IMEState;
 enum nsLinkState {
   eLinkState_Unvisited  = 1,
   eLinkState_Visited    = 2,
   eLinkState_NotLink    = 3 
 };
 
 // IID for the nsIContent interface
 #define NS_ICONTENT_IID \
-{ 0x52cebfc8, 0x79ba, 0x4e38, \
-  { 0x8a, 0x4c, 0x7f, 0x9d, 0xb1, 0xa2, 0xb6, 0x1d } }
+{ 0x8e1bab9d, 0x8815, 0x4d2c, \
+  { 0xa2, 0x4d, 0x7a, 0xba, 0x52, 0x39, 0xdc, 0x22 } }
 
 /**
  * A node of content in a document's content model. This interface
  * is supported by all content objects.
  */
 class nsIContent : public nsINode {
 public:
   typedef mozilla::widget::IMEState IMEState;
@@ -576,20 +576,22 @@ public:
 
   /**
    * The method focuses (or activates) element that accesskey is bound to. It is
    * called when accesskey is activated.
    *
    * @param aKeyCausesActivation - if true then element should be activated
    * @param aIsTrustedEvent - if true then event that is cause of accesskey
    *                          execution is trusted.
+   * @return true if the focus was changed.
    */
-  virtual void PerformAccesskey(bool aKeyCausesActivation,
+  virtual bool PerformAccesskey(bool aKeyCausesActivation,
                                 bool aIsTrustedEvent)
   {
+    return false;
   }
 
   /*
    * Get desired IME state for the content.
    *
    * @return The desired IME status for the content.
    *         This is a combination of an IME enabled value and
    *         an IME open value of widget::IMEState.
--- a/dom/html/HTMLLabelElement.cpp
+++ b/dom/html/HTMLLabelElement.cpp
@@ -213,40 +213,44 @@ HTMLLabelElement::Reset()
 }
 
 NS_IMETHODIMP
 HTMLLabelElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
 {
   return NS_OK;
 }
 
-void
+bool
 HTMLLabelElement::PerformAccesskey(bool aKeyCausesActivation,
                                    bool aIsTrustedEvent)
 {
   if (!aKeyCausesActivation) {
     nsRefPtr<Element> element = GetLabeledElement();
-    if (element)
-      element->PerformAccesskey(aKeyCausesActivation, aIsTrustedEvent);
+    if (element) {
+      return element->PerformAccesskey(aKeyCausesActivation, aIsTrustedEvent);
+    }
   } else {
     nsPresContext *presContext = GetPresContext(eForUncomposedDoc);
-    if (!presContext)
-      return;
+    if (!presContext) {
+      return false;
+    }
 
     // Click on it if the users prefs indicate to do so.
     WidgetMouseEvent event(aIsTrustedEvent, eMouseClick,
                            nullptr, WidgetMouseEvent::eReal);
     event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD;
 
     nsAutoPopupStatePusher popupStatePusher(aIsTrustedEvent ?
                                             openAllowed : openAbused);
 
     EventDispatcher::Dispatch(static_cast<nsIContent*>(this), presContext,
                               &event);
   }
+
+  return aKeyCausesActivation;
 }
 
 nsGenericHTMLElement*
 HTMLLabelElement::GetLabeledElement() const
 {
   nsAutoString elementId;
 
   if (!GetAttr(kNameSpaceID_None, nsGkAtoms::_for, elementId)) {
--- a/dom/html/HTMLLabelElement.h
+++ b/dom/html/HTMLLabelElement.h
@@ -64,17 +64,17 @@ public:
   NS_IMETHOD Reset() override;
   NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission) override;
 
   virtual bool IsDisabled() const override { return false; }
 
   // nsIContent
   virtual nsresult PostHandleEvent(
                      EventChainPostVisitor& aVisitor) override;
-  virtual void PerformAccesskey(bool aKeyCausesActivation,
+  virtual bool PerformAccesskey(bool aKeyCausesActivation,
                                 bool aIsTrustedEvent) override;
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
 
   nsGenericHTMLElement* GetLabeledElement() const;
 protected:
   virtual ~HTMLLabelElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
--- a/dom/html/HTMLLegendElement.cpp
+++ b/dom/html/HTMLLegendElement.cpp
@@ -123,23 +123,24 @@ HTMLLegendElement::Focus(ErrorResult& aE
   }
 
   nsCOMPtr<nsIDOMElement> result;
   aError = fm->MoveFocus(nullptr, this, nsIFocusManager::MOVEFOCUS_FORWARD,
                          nsIFocusManager::FLAG_NOPARENTFRAME,
                          getter_AddRefs(result));
 }
 
-void
+bool
 HTMLLegendElement::PerformAccesskey(bool aKeyCausesActivation,
                                     bool aIsTrustedEvent)
 {
   // just use the same behaviour as the focus method
   ErrorResult rv;
   Focus(rv);
+  return NS_SUCCEEDED(rv.StealNSResult());
 }
 
 already_AddRefed<HTMLFormElement>
 HTMLLegendElement::GetForm()
 {
   Element* form = GetFormElement();
   MOZ_ASSERT_IF(form, form->IsHTMLElement(nsGkAtoms::form));
   nsRefPtr<HTMLFormElement> ret = static_cast<HTMLFormElement*>(form);
--- a/dom/html/HTMLLegendElement.h
+++ b/dom/html/HTMLLegendElement.h
@@ -22,17 +22,17 @@ public:
   {
   }
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLLegendElement, legend)
 
   using nsGenericHTMLElement::Focus;
   virtual void Focus(ErrorResult& aError) override;
 
-  virtual void PerformAccesskey(bool aKeyCausesActivation,
+  virtual bool PerformAccesskey(bool aKeyCausesActivation,
                                 bool aIsTrustedEvent) override;
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -2734,42 +2734,50 @@ nsGenericHTMLElement::RegUnRegAccessKey(
     if (aDoReg) {
       esm->RegisterAccessKey(this, (uint32_t)accessKey.First());
     } else {
       esm->UnregisterAccessKey(this, (uint32_t)accessKey.First());
     }
   }
 }
 
-void
+bool
 nsGenericHTMLElement::PerformAccesskey(bool aKeyCausesActivation,
                                        bool aIsTrustedEvent)
 {
   nsPresContext* presContext = GetPresContext(eForUncomposedDoc);
-  if (!presContext)
-    return;
+  if (!presContext) {
+    return false;
+  }
 
   // It's hard to say what HTML4 wants us to do in all cases.
-  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  bool focused = true;
+  nsFocusManager* fm = nsFocusManager::GetFocusManager();
   if (fm) {
     fm->SetFocus(this, nsIFocusManager::FLAG_BYKEY);
+
+    // Return true if the element became the current focus within its window.
+    nsPIDOMWindow* window = OwnerDoc()->GetWindow();
+    focused = (window && window->GetFocusedNode());
   }
 
   if (aKeyCausesActivation) {
     // Click on it if the users prefs indicate to do so.
     WidgetMouseEvent event(aIsTrustedEvent, eMouseClick, nullptr,
                            WidgetMouseEvent::eReal);
     event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD;
 
     nsAutoPopupStatePusher popupStatePusher(aIsTrustedEvent ?
                                             openAllowed : openAbused);
 
     EventDispatcher::Dispatch(static_cast<nsIContent*>(this),
                               presContext, &event);
   }
+
+  return focused;
 }
 
 const nsAttrName*
 nsGenericHTMLElement::InternalGetExistingAttrNameFromQName(const nsAString& aStr) const
 {
   if (IsInHTMLDocument()) {
     nsAutoString lower;
     nsContentUtils::ASCIIToLower(aStr, lower);
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -592,17 +592,17 @@ public:
   }
   /**
    * Returns true if a subclass is not allowed to override the value returned
    * in aIsFocusable.
    */
   virtual bool IsHTMLFocusable(bool aWithMouse,
                                bool *aIsFocusable,
                                int32_t *aTabIndex);
-  virtual void PerformAccesskey(bool aKeyCausesActivation,
+  virtual bool PerformAccesskey(bool aKeyCausesActivation,
                                 bool aIsTrustedEvent) override;
 
   /**
    * Check if an event for an anchor can be handled
    * @return true if the event can be handled, false otherwise
    */
   bool CheckHandleEventForAnchorsPreconditions(
          mozilla::EventChainVisitor& aVisitor);
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -615,17 +615,17 @@ nsXULElement::IsFocusableInternal(int32_
     } else {
       shouldFocus = *aTabIndex >= 0;
     }
   }
 
   return shouldFocus;
 }
 
-void
+bool
 nsXULElement::PerformAccesskey(bool aKeyCausesActivation,
                                bool aIsTrustedEvent)
 {
     nsCOMPtr<nsIContent> content(this);
 
     if (IsXULElement(nsGkAtoms::label)) {
         nsCOMPtr<nsIDOMElement> element;
 
@@ -638,57 +638,67 @@ nsXULElement::PerformAccesskey(bool aKey
                 do_QueryInterface(content->GetUncomposedDoc());
             if (domDocument)
                 domDocument->GetElementById(control, getter_AddRefs(element));
         }
         // here we'll either change |content| to the element referenced by
         // |element|, or clear it.
         content = do_QueryInterface(element);
 
-        if (!content)
-            return;
+        if (!content) {
+            return false;
+        }
     }
 
     nsIFrame* frame = content->GetPrimaryFrame();
-    if (!frame || !frame->IsVisibleConsideringAncestors())
-        return;
-
+    if (!frame || !frame->IsVisibleConsideringAncestors()) {
+        return false;
+    }
+
+    bool focused = false;
     nsXULElement* elm = FromContent(content);
     if (elm) {
         // Define behavior for each type of XUL element.
         if (!content->IsXULElement(nsGkAtoms::toolbarbutton)) {
           nsIFocusManager* fm = nsFocusManager::GetFocusManager();
           if (fm) {
-            nsCOMPtr<nsIDOMElement> element;
+            nsCOMPtr<nsIDOMElement> elementToFocus;
             // for radio buttons, focus the radiogroup instead
             if (content->IsXULElement(nsGkAtoms::radio)) {
               nsCOMPtr<nsIDOMXULSelectControlItemElement> controlItem(do_QueryInterface(content));
               if (controlItem) {
                 bool disabled;
                 controlItem->GetDisabled(&disabled);
                 if (!disabled) {
                   nsCOMPtr<nsIDOMXULSelectControlElement> selectControl;
                   controlItem->GetControl(getter_AddRefs(selectControl));
-                  element = do_QueryInterface(selectControl);
+                  elementToFocus = do_QueryInterface(selectControl);
                 }
               }
             } else {
-              element = do_QueryInterface(content);
+              elementToFocus = do_QueryInterface(content);
             }
-            if (element)
-              fm->SetFocus(element, nsIFocusManager::FLAG_BYKEY);
+            if (elementToFocus) {
+              fm->SetFocus(elementToFocus, nsIFocusManager::FLAG_BYKEY);
+
+              // Return true if the element became focused.
+              nsPIDOMWindow* window = OwnerDoc()->GetWindow();
+              focused = (window && window->GetFocusedNode());
+            }
           }
         }
         if (aKeyCausesActivation &&
             !content->IsAnyOfXULElements(nsGkAtoms::textbox, nsGkAtoms::menulist)) {
           elm->ClickWithInputSource(nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD);
         }
     } else {
-        content->PerformAccesskey(aKeyCausesActivation, aIsTrustedEvent);
+        return content->PerformAccesskey(aKeyCausesActivation, aIsTrustedEvent);
     }
+
+    return focused;
 }
 
 //----------------------------------------------------------------------
 
 void
 nsXULElement::AddListenerFor(const nsAttrName& aName,
                              bool aCompileEventHandlers)
 {
--- a/dom/xul/nsXULElement.h
+++ b/dom/xul/nsXULElement.h
@@ -394,17 +394,17 @@ public:
 
 #ifdef DEBUG
     virtual void List(FILE* out, int32_t aIndent) const override;
     virtual void DumpContent(FILE* out, int32_t aIndent,bool aDumpAll) const override
     {
     }
 #endif
 
-    virtual void PerformAccesskey(bool aKeyCausesActivation,
+    virtual bool PerformAccesskey(bool aKeyCausesActivation,
                                   bool aIsTrustedEvent) override;
     nsresult ClickWithInputSource(uint16_t aInputSource);
 
     virtual nsIContent *GetBindingParent() const override;
     virtual bool IsNodeOfType(uint32_t aFlags) const override;
     virtual bool IsFocusableInternal(int32_t* aTabIndex, bool aWithMouse) override;
 
     NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;