Bug 1364896 - Part 1 - Propagate trigger event inputSource to XUL popupshowing events. r=masayuki draft
authorJohann Hofmann <jhofmann@mozilla.com>
Fri, 09 Jun 2017 16:49:40 +0200
changeset 600793 4f2cacf2e8b603bc206595a1f5e5c15b7ea04bd0
parent 600694 8f80d594c08d5c7a112e5d4b9eb44ffca717eb7b
child 600794 8bbf0390a2c0dc82cfe6bb073ee0e6447f4afc81
push id65882
push userbmo:jhofmann@mozilla.com
push dateTue, 27 Jun 2017 21:08:20 +0000
reviewersmasayuki
bugs1364896
milestone56.0a1
Bug 1364896 - Part 1 - Propagate trigger event inputSource to XUL popupshowing events. r=masayuki For resizing context menus when accessed through touch, it is useful for frontend code to know the inputSource of the action that triggered a menu during the popupshowing event. MozReview-Commit-ID: DvPDHvPgoUN
layout/xul/nsXULPopupManager.cpp
layout/xul/nsXULPopupManager.h
--- a/layout/xul/nsXULPopupManager.cpp
+++ b/layout/xul/nsXULPopupManager.cpp
@@ -766,17 +766,17 @@ nsXULPopupManager::ShowMenu(nsIContent *
       new nsXULPopupShowingEvent(popupFrame->GetContent(),
                                  parentIsContextMenu, aSelectFirstItem);
     aMenu->OwnerDoc()->Dispatch("nsXULPopupShowingEvent",
                                 TaskCategory::Other,
                                 event.forget());
   }
   else {
     nsCOMPtr<nsIContent> popupContent = popupFrame->GetContent();
-    FirePopupShowingEvent(popupContent, parentIsContextMenu, aSelectFirstItem);
+    FirePopupShowingEvent(popupContent, parentIsContextMenu, aSelectFirstItem, nullptr);
   }
 }
 
 void
 nsXULPopupManager::ShowPopup(nsIContent* aPopup,
                              nsIContent* aAnchorContent,
                              const nsAString& aPosition,
                              int32_t aXPos, int32_t aYPos,
@@ -790,34 +790,34 @@ nsXULPopupManager::ShowPopup(nsIContent*
     return;
 
   nsCOMPtr<nsIContent> triggerContent;
   InitTriggerEvent(aTriggerEvent, aPopup, getter_AddRefs(triggerContent));
 
   popupFrame->InitializePopup(aAnchorContent, triggerContent, aPosition,
                               aXPos, aYPos, MenuPopupAnchorType_Node, aAttributesOverride);
 
-  FirePopupShowingEvent(aPopup, aIsContextMenu, aSelectFirstItem);
+  FirePopupShowingEvent(aPopup, aIsContextMenu, aSelectFirstItem, aTriggerEvent);
 }
 
 void
 nsXULPopupManager::ShowPopupAtScreen(nsIContent* aPopup,
                                      int32_t aXPos, int32_t aYPos,
                                      bool aIsContextMenu,
                                      nsIDOMEvent* aTriggerEvent)
 {
   nsMenuPopupFrame* popupFrame = GetPopupFrameForContent(aPopup, true);
   if (!popupFrame || !MayShowPopup(popupFrame))
     return;
 
   nsCOMPtr<nsIContent> triggerContent;
   InitTriggerEvent(aTriggerEvent, aPopup, getter_AddRefs(triggerContent));
 
   popupFrame->InitializePopupAtScreen(triggerContent, aXPos, aYPos, aIsContextMenu);
-  FirePopupShowingEvent(aPopup, aIsContextMenu, false);
+  FirePopupShowingEvent(aPopup, aIsContextMenu, false, aTriggerEvent);
 }
 
 void
 nsXULPopupManager::ShowPopupAtScreenRect(nsIContent* aPopup,
                                          const nsAString& aPosition,
                                          const nsIntRect& aRect,
                                          bool aIsContextMenu,
                                          bool aAttributesOverride,
@@ -828,17 +828,17 @@ nsXULPopupManager::ShowPopupAtScreenRect
     return;
 
   nsCOMPtr<nsIContent> triggerContent;
   InitTriggerEvent(aTriggerEvent, aPopup, getter_AddRefs(triggerContent));
 
   popupFrame->InitializePopupAtRect(triggerContent, aPosition,
                                     aRect, aAttributesOverride);
 
-  FirePopupShowingEvent(aPopup, aIsContextMenu, false);
+  FirePopupShowingEvent(aPopup, aIsContextMenu, false, aTriggerEvent);
 }
 
 void
 nsXULPopupManager::ShowTooltipAtScreen(nsIContent* aPopup,
                                        nsIContent* aTriggerContent,
                                        int32_t aXPos, int32_t aYPos)
 {
   nsMenuPopupFrame* popupFrame = GetPopupFrameForContent(aPopup, true);
@@ -857,17 +857,17 @@ nsXULPopupManager::ShowTooltipAtScreen(n
     nsIWidget *rootWidget = rootPresContext->GetRootWidget();
     if (rootWidget) {
       mCachedMousePoint -= rootWidget->WidgetToScreenOffset();
     }
   }
 
   popupFrame->InitializePopupAtScreen(aTriggerContent, aXPos, aYPos, false);
 
-  FirePopupShowingEvent(aPopup, false, false);
+  FirePopupShowingEvent(aPopup, false, false, nullptr);
 }
 
 void
 nsXULPopupManager::ShowPopupWithAnchorAlign(nsIContent* aPopup,
                                             nsIContent* aAnchorContent,
                                             nsAString& aAnchor,
                                             nsAString& aAlign,
                                             int32_t aXPos, int32_t aYPos,
@@ -876,17 +876,17 @@ nsXULPopupManager::ShowPopupWithAnchorAl
   nsMenuPopupFrame* popupFrame = GetPopupFrameForContent(aPopup, true);
   if (!popupFrame || !MayShowPopup(popupFrame))
     return;
 
   InitTriggerEvent(nullptr, nullptr, nullptr);
 
   popupFrame->InitializePopupWithAnchorAlign(aAnchorContent, aAnchor,
                                              aAlign, aXPos, aYPos);
-  FirePopupShowingEvent(aPopup, aIsContextMenu, false);
+  FirePopupShowingEvent(aPopup, aIsContextMenu, false, nullptr);
 }
 
 static void
 CheckCaretDrawingState()
 {
   // There is 1 caret per document, we need to find the focused
   // document and erase its caret.
   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
@@ -1424,17 +1424,18 @@ nsXULPopupManager::ExecuteMenu(nsIConten
   aMenu->OwnerDoc()->Dispatch("nsXULMenuCommandEvent",
                               TaskCategory::Other,
                               event.forget());
 }
 
 void
 nsXULPopupManager::FirePopupShowingEvent(nsIContent* aPopup,
                                          bool aIsContextMenu,
-                                         bool aSelectFirstItem)
+                                         bool aSelectFirstItem,
+                                         nsIDOMEvent* aTriggerEvent)
 {
   nsCOMPtr<nsIContent> popup = aPopup; // keep a strong reference to the popup
 
   nsMenuPopupFrame* popupFrame = do_QueryFrame(aPopup->GetPrimaryFrame());
   if (!popupFrame)
     return;
 
   nsPresContext *presContext = popupFrame->PresContext();
@@ -1470,16 +1471,24 @@ nsXULPopupManager::FirePopupShowingEvent
   if (rootPresContext) {
     rootPresContext->PresShell()->GetViewManager()->
       GetRootWidget(getter_AddRefs(event.mWidget));
   }
   else {
     event.mWidget = nullptr;
   }
 
+  if (aTriggerEvent) {
+    WidgetMouseEventBase* mouseEvent =
+      aTriggerEvent->WidgetEventPtr()->AsMouseEventBase();
+    if (mouseEvent) {
+      event.inputSource = mouseEvent->inputSource;
+    }
+  }
+
   event.mRefPoint = mCachedMousePoint;
   event.mModifiers = mCachedModifiers;
   EventDispatcher::Dispatch(popup, presContext, &event, nullptr, &status);
 
   mCachedMousePoint = LayoutDeviceIntPoint(0, 0);
   mOpeningPopup = nullptr;
 
   mCachedModifiers = 0;
@@ -2735,17 +2744,17 @@ nsXULPopupManager::KeyPress(nsIDOMKeyEve
   return NS_OK; // I am consuming event
 }
 
 NS_IMETHODIMP
 nsXULPopupShowingEvent::Run()
 {
   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
   if (pm) {
-    pm->FirePopupShowingEvent(mPopup, mIsContextMenu, mSelectFirstItem);
+    pm->FirePopupShowingEvent(mPopup, mIsContextMenu, mSelectFirstItem, nullptr);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULPopupHidingEvent::Run()
 {
--- a/layout/xul/nsXULPopupManager.h
+++ b/layout/xul/nsXULPopupManager.h
@@ -726,20 +726,24 @@ protected:
                          bool aDeselectMenu);
 
   /**
    * Fire a popupshowing event on the popup and then open the popup.
    *
    * aPopup - the popup to open
    * aIsContextMenu - true for context menus
    * aSelectFirstItem - true to select the first item in the menu
+   * aTriggerEvent - the event that triggered the showing event.
+   *                 This is currently used to propagate the
+   *                 inputSource attribute. May be null.
    */
   void FirePopupShowingEvent(nsIContent* aPopup,
                              bool aIsContextMenu,
-                             bool aSelectFirstItem);
+                             bool aSelectFirstItem,
+                             nsIDOMEvent* aTriggerEvent);
 
   /**
    * Fire a popuphiding event and then hide the popup. This will be called
    * recursively if aNextPopup and aLastPopup are set in order to hide a chain
    * of open menus. If these are not set, only one popup is closed. However,
    * if the popup type indicates a menu, yet the next popup is not a menu,
    * then this ends the closing of popups. This allows a menulist inside a
    * non-menu to close up the menu but not close up the panel it is contained