Bug 1221947 - part 1: add BYTOUCH flag to nsIFocusManager, r=jaws,smaug a=ritu
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Thu, 12 Nov 2015 16:35:20 +0000
changeset 303761 8e13fe7ab3da6658e6dcb184950b412367fbaeba
parent 303760 2c5f51e5d0afeff3b547ecaa3d45965a4f5a8cda
child 303762 54f8c04cc8d7c9b951b38c94ca787de688856ea9
push id5392
push userraliiev@mozilla.com
push dateMon, 14 Dec 2015 20:08:23 +0000
treeherdermozilla-beta@16ce8562a975 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws, smaug, ritu
bugs1221947
milestone44.0a2
Bug 1221947 - part 1: add BYTOUCH flag to nsIFocusManager, r=jaws,smaug a=ritu IGNORE IDL
browser/components/search/content/search.xml
dom/events/EventStateManager.cpp
dom/html/HTMLButtonElement.cpp
dom/html/HTMLLabelElement.cpp
dom/interfaces/base/nsIFocusManager.idl
dom/xul/nsXULPopupListener.cpp
dom/xul/nsXULPopupListener.h
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -483,17 +483,17 @@
         }
 
         // Don't open the suggestions if there is no text in the textbox.
         if (!this._textbox.value)
           return;
 
         // Don't open the suggestions if the mouse was used to focus the
         // textbox, that will be taken care of in the click handler.
-        if (Services.focus.getLastFocusMethod(window) == Services.focus.FLAG_BYMOUSE)
+        if (Services.focus.getLastFocusMethod(window) & Services.focus.FLAG_BYMOUSE)
           return;
 
         this.openSuggestionsPanel();
       ]]></handler>
 
       <handler event="mousedown" phase="capturing">
       <![CDATA[
         if (event.originalTarget.getAttribute("anonid") == "searchbar-search-button") {
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -2969,20 +2969,25 @@ EventStateManager::PostHandleEvent(nsPre
           // Another effect of mouse clicking, handled in nsSelection, is that
           // it should update the caret position to where the mouse was
           // clicked. Because the focus is cleared when clicking on a
           // non-focusable node, the next press of the tab key will cause
           // focus to be shifted from the caret position instead of the root.
           if (newFocus && currFrame) {
             // use the mouse flag and the noscroll flag so that the content
             // doesn't unexpectedly scroll when clicking an element that is
-            // only hald visible
+            // only half visible
+            uint32_t flags = nsIFocusManager::FLAG_BYMOUSE |
+                             nsIFocusManager::FLAG_NOSCROLL;
+            // If this was a touch-generated event, pass that information:
+            if (mouseEvent->inputSource == nsIDOMMouseEvent::MOZ_SOURCE_TOUCH) {
+              flags |= nsIFocusManager::FLAG_BYTOUCH;
+            }
             nsCOMPtr<nsIDOMElement> newFocusElement = do_QueryInterface(newFocus);
-            fm->SetFocus(newFocusElement, nsIFocusManager::FLAG_BYMOUSE |
-                                          nsIFocusManager::FLAG_NOSCROLL);
+            fm->SetFocus(newFocusElement, flags);
           }
           else if (!suppressBlur) {
             // clear the focus within the frame and then set it as the
             // focused frame
             EnsureDocument(mPresContext);
             if (mDocument) {
 #ifdef XP_MACOSX
               if (!activeContent || !activeContent->IsXULElement())
--- a/dom/html/HTMLButtonElement.cpp
+++ b/dom/html/HTMLButtonElement.cpp
@@ -312,19 +312,25 @@ HTMLButtonElement::PostHandleEvent(Event
           if (mouseEvent->button == WidgetMouseEvent::eLeftButton) {
             if (mouseEvent->mFlags.mIsTrusted) {
               EventStateManager* esm =
                 aVisitor.mPresContext->EventStateManager();
               EventStateManager::SetActiveManager(
                 static_cast<EventStateManager*>(esm), this);
             }
             nsIFocusManager* fm = nsFocusManager::GetFocusManager();
-            if (fm)
-              fm->SetFocus(this, nsIFocusManager::FLAG_BYMOUSE |
-                                 nsIFocusManager::FLAG_NOSCROLL);
+            if (fm) {
+              uint32_t flags = nsIFocusManager::FLAG_BYMOUSE |
+                               nsIFocusManager::FLAG_NOSCROLL;
+              // If this was a touch-generated event, pass that information:
+              if (mouseEvent->inputSource == nsIDOMMouseEvent::MOZ_SOURCE_TOUCH) {
+                flags |= nsIFocusManager::FLAG_BYTOUCH;
+              }
+              fm->SetFocus(this, flags);
+            }
             mouseEvent->mFlags.mMultipleActionsPrevented = true;
           } else if (mouseEvent->button == WidgetMouseEvent::eMiddleButton ||
                      mouseEvent->button == WidgetMouseEvent::eRightButton) {
             // cancel all of these events for buttons
             //XXXsmaug What to do with these events? Why these should be cancelled?
             if (aVisitor.mDOMEvent) {
               aVisitor.mDOMEvent->StopPropagation();
             }
--- a/dom/html/HTMLLabelElement.cpp
+++ b/dom/html/HTMLLabelElement.cpp
@@ -170,18 +170,20 @@ HTMLLabelElement::PostHandleEvent(EventC
               // flag is used and we want to select the text on label clicks as
               // well.
               // If the label has been clicked by the user, we also want to
               // pass FLAG_BYMOUSE so that we get correct focus ring behavior,
               // but we don't want to pass FLAG_BYMOUSE if this click event was
               // caused by the user pressing an accesskey.
               nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(content);
               bool byMouse = (mouseEvent->inputSource != nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD);
+              bool byTouch = (mouseEvent->inputSource == nsIDOMMouseEvent::MOZ_SOURCE_TOUCH);
               fm->SetFocus(elem, nsIFocusManager::FLAG_BYMOVEFOCUS |
-                                 (byMouse ? nsIFocusManager::FLAG_BYMOUSE : 0));
+                                 (byMouse ? nsIFocusManager::FLAG_BYMOUSE : 0) |
+                                 (byTouch ? nsIFocusManager::FLAG_BYTOUCH : 0));
             }
           }
           // Dispatch a new click event to |content|
           //    (For compatibility with IE, we do only left click.  If
           //    we wanted to interpret the HTML spec very narrowly, we
           //    would do nothing.  If we wanted to do something
           //    sensible, we might send more events through like
           //    this.)  See bug 7554, bug 49897, and bug 96813.
--- a/dom/interfaces/base/nsIFocusManager.idl
+++ b/dom/interfaces/base/nsIFocusManager.idl
@@ -190,16 +190,22 @@ interface nsIFocusManager : nsISupports
   const unsigned long FLAG_BYMOVEFOCUS = 0x4000;
 
   /**
    * Always show the focus ring or other indicator of focus, regardless of
    * other state.
    */
   const unsigned long FLAG_SHOWRING = 0x100000;
 
+  /**
+   * Focus is changing due to a touch operation that generated a mouse event.
+   * Normally used in conjunction with FLAG_BYMOUSE.
+   */
+  const unsigned long FLAG_BYTOUCH = 0x200000;
+
   // these constants are used with the aType argument to MoveFocus
 
   /** move focus forward one element, used when pressing TAB */
   const unsigned long MOVEFOCUS_FORWARD = 1;
   /** move focus backward one element, used when pressing Shift+TAB */
   const unsigned long MOVEFOCUS_BACKWARD = 2;
   /** move focus forward to the next frame document, used when pressing F6 */
   const unsigned long MOVEFOCUS_FORWARDDOC = 3;
--- a/dom/xul/nsXULPopupListener.cpp
+++ b/dom/xul/nsXULPopupListener.cpp
@@ -190,19 +190,22 @@ nsXULPopupListener::HandleEvent(nsIDOMEv
   if (!mIsContext) {
     if (targetContent &&
         targetContent->IsAnyOfXULElements(nsGkAtoms::menu, nsGkAtoms::menuitem))
       return NS_OK;
   }
 
   if (mIsContext) {
 #ifndef NS_CONTEXT_MENU_IS_MOUSEUP
+    uint16_t inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
+    mouseEvent->GetMozInputSource(&inputSource);
+    bool isTouch = inputSource == nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
     // If the context menu launches on mousedown,
     // we have to fire focus on the content we clicked on
-    FireFocusOnTargetContent(targetNode);
+    FireFocusOnTargetContent(targetNode, isTouch);
 #endif
   }
   else {
     // Only open popups when the left mouse button is down.
     mouseEvent->GetButton(&button);
     if (button != 0)
       return NS_OK;
   }
@@ -211,17 +214,17 @@ nsXULPopupListener::HandleEvent(nsIDOMEv
   // in the right situations.
   LaunchPopup(aEvent, targetContent);
 
   return NS_OK;
 }
 
 #ifndef NS_CONTEXT_MENU_IS_MOUSEUP
 nsresult
-nsXULPopupListener::FireFocusOnTargetContent(nsIDOMNode* aTargetNode)
+nsXULPopupListener::FireFocusOnTargetContent(nsIDOMNode* aTargetNode, bool aIsTouch)
 {
   nsresult rv;
   nsCOMPtr<nsIDOMDocument> domDoc;
   rv = aTargetNode->GetOwnerDocument(getter_AddRefs(domDoc));
   if(NS_SUCCEEDED(rv) && domDoc)
   {
     nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
 
@@ -257,18 +260,22 @@ nsXULPopupListener::FireFocusOnTargetCon
           }
         }
         currFrame = currFrame->GetParent();
     } 
 
     nsIFocusManager* fm = nsFocusManager::GetFocusManager();
     if (fm) {
       if (element) {
-        fm->SetFocus(element, nsIFocusManager::FLAG_BYMOUSE |
-                              nsIFocusManager::FLAG_NOSCROLL);
+        uint32_t focusFlags = nsIFocusManager::FLAG_BYMOUSE |
+                              nsIFocusManager::FLAG_NOSCROLL;
+        if (aIsTouch) {
+          focusFlags |= nsIFocusManager::FLAG_BYTOUCH;
+        }
+        fm->SetFocus(element, focusFlags);
       } else if (!suppressBlur) {
         nsPIDOMWindow *window = doc->GetWindow();
         fm->ClearFocus(window);
       }
     }
 
     EventStateManager* esm = context->EventStateManager();
     nsCOMPtr<nsIContent> focusableContent = do_QueryInterface(element);
--- a/dom/xul/nsXULPopupListener.h
+++ b/dom/xul/nsXULPopupListener.h
@@ -40,17 +40,17 @@ protected:
     virtual nsresult LaunchPopup(nsIDOMEvent* aEvent, nsIContent* aTargetContent);
 
     // close the popup when the listener goes away
     virtual void ClosePopup();
 
 private:
 #ifndef NS_CONTEXT_MENU_IS_MOUSEUP
     // When a context menu is opened, focus the target of the contextmenu event.
-    nsresult FireFocusOnTargetContent(nsIDOMNode* aTargetNode);
+    nsresult FireFocusOnTargetContent(nsIDOMNode* aTargetNode, bool aIsTouch);
 #endif
 
     // |mElement| is the node to which this listener is attached.
     nsCOMPtr<mozilla::dom::Element> mElement;
 
     // The popup that is getting shown on top of mElement.
     nsCOMPtr<nsIContent> mPopupContent;