Bug 1466208 - part 9: Create PresShell::EventHandler::MaybeHandleEventWithAnotherPresShell() to handle event with another PresShell if necessary r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Sat, 02 Feb 2019 02:20:25 +0000
changeset 456575 1d868390c454251d1ad828eada546bcdf3b0c302
parent 456574 8a968b7beaba6fb6f5e6323298db98501e28ef44
child 456576 43a3aa2199c12427c9784a9cdbb89f76cf1296a5
push id35490
push useraiakab@mozilla.com
push dateSun, 03 Feb 2019 09:50:26 +0000
treeherdermozilla-central@12b2328eedd1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1466208
milestone67.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 1466208 - part 9: Create PresShell::EventHandler::MaybeHandleEventWithAnotherPresShell() to handle event with another PresShell if necessary r=smaug Let's move the redirection of coming event in PresShell::EventHandler::HandleEvent() into a method. This makes the caller easier to read. Differential Revision: https://phabricator.services.mozilla.com/D16959
layout/base/PresShell.cpp
layout/base/PresShell.h
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -6516,32 +6516,23 @@ nsresult PresShell::EventHandler::Handle
       NS_WARNING(warning.get());
     }
 #endif
     nsContentUtils::WarnScriptWasIgnored(GetDocument());
     return NS_OK;
   }
 
   if (!aDontRetargetEvents) {
-    RefPtr<Document> retargetEventDoc;
-    if (!GetRetargetEventDocument(aGUIEvent,
-                                  getter_AddRefs(retargetEventDoc))) {
-      return NS_OK;  // Not need to return error.
-    }
-
-    if (retargetEventDoc) {
-      nsIFrame* frame =
-          GetFrameForHandlingEventWith(aGUIEvent, retargetEventDoc, aFrame);
-      if (!frame) {
-        return NS_OK;  // Not need to return error.
-      }
-      if (frame != aFrame) {
-        nsCOMPtr<nsIPresShell> shell = frame->PresContext()->GetPresShell();
-        return shell->HandleEvent(frame, aGUIEvent, true, aEventStatus);
-      }
+    // If aGUIEvent should be handled in another PresShell, we should call its
+    // HandleEvent() and do nothing here.
+    nsresult rv = NS_OK;
+    if (MaybeHandleEventWithAnotherPresShell(aFrame, aGUIEvent, aEventStatus,
+                                             &rv)) {
+      // Handled by another PresShell or nobody can handle the event.
+      return rv;
     }
   }
 
   if (aGUIEvent->mClass == eKeyboardEventClass && GetDocument() &&
       GetDocument()->EventHandlingSuppressed()) {
     if (aGUIEvent->mMessage == eKeyDown) {
       mPresShell->mNoDelayedKeyEvents = true;
     } else if (!mPresShell->mNoDelayedKeyEvents) {
@@ -7215,16 +7206,58 @@ nsIFrame* PresShell::EventHandler::GetFr
       aGUIEvent->IsContentCommandEvent()) {
     return nullptr;
   }
 
   // Otherwise, use nearest ancestor frame which includes the PresShell.
   return GetNearestFrameContainingPresShell(retargetPresShell);
 }
 
+bool PresShell::EventHandler::MaybeHandleEventWithAnotherPresShell(
+    nsIFrame* aFrameForPresShell, WidgetGUIEvent* aGUIEvent,
+    nsEventStatus* aEventStatus, nsresult* aRv) {
+  MOZ_ASSERT(aGUIEvent);
+  MOZ_ASSERT(aEventStatus);
+  MOZ_ASSERT(aRv);
+
+  *aRv = NS_OK;
+
+  RefPtr<Document> retargetEventDoc;
+  if (!GetRetargetEventDocument(aGUIEvent, getter_AddRefs(retargetEventDoc))) {
+    // Nobody can handle this event.  So, treat as handled by somebody to make
+    // caller do nothing anymore.
+    return true;
+  }
+
+  // If there is no proper retarget document, the caller should handle the
+  // event by itself.
+  if (!retargetEventDoc) {
+    return false;
+  }
+
+  nsIFrame* frame = GetFrameForHandlingEventWith(aGUIEvent, retargetEventDoc,
+                                                 aFrameForPresShell);
+  if (!frame) {
+    // Nobody can handle this event.  So, treat as handled by somebody to make
+    // caller do nothing anymore.
+    return true;
+  }
+
+  // If we reached same frame as set to HandleEvent(), the caller should handle
+  // the event by itself.
+  if (frame == aFrameForPresShell) {
+    return false;
+  }
+
+  // We need to handle aGUIEvent with another PresShell.
+  nsCOMPtr<nsIPresShell> shell = frame->PresContext()->GetPresShell();
+  *aRv = shell->HandleEvent(frame, aGUIEvent, true, aEventStatus);
+  return true;
+}
+
 Document* PresShell::GetPrimaryContentDocument() {
   nsPresContext* context = GetPresContext();
   if (!context || !context->IsRoot()) {
     return nullptr;
   }
 
   nsCOMPtr<nsIDocShellTreeItem> shellAsTreeItem = context->GetDocShell();
   if (!shellAsTreeItem) {
--- a/layout/base/PresShell.h
+++ b/layout/base/PresShell.h
@@ -611,16 +611,38 @@ class PresShell final : public nsIPresSh
      *                                  Otherwise, caller should handle it with
      *                                  another PresShell which is result of
      *                                  nsIFrame::PresContext()->GetPresShell().
      */
     nsIFrame* GetFrameForHandlingEventWith(WidgetGUIEvent* aGUIEvent,
                                            Document* aRetargetDocument,
                                            nsIFrame* aFrameForPresShell);
 
+    /**
+     * MaybeHandleEventWithAnotherPresShell() may handle aGUIEvent with another
+     * PresShell.
+     *
+     * @param aFrameForPresShell        Set aFrame of HandleEvent() which called
+     *                                  this method.
+     * @param aGUIEvent                 Handling event.
+     * @param aEventStatus              [in/out] EventStatus of aGUIEvent.
+     * @param aRv                       [out] Returns error if this gets an
+     *                                  error handling the event.
+     * @return                          false if caller needs to keep handling
+     *                                  the event by itself.
+     *                                  true if caller shouldn't keep handling
+     *                                  the event.  Note that when no PresShell
+     *                                  can handle the event, this returns true.
+     */
+    MOZ_CAN_RUN_SCRIPT
+    bool MaybeHandleEventWithAnotherPresShell(nsIFrame* aFrameForPresShell,
+                                              WidgetGUIEvent* aGUIEvent,
+                                              nsEventStatus* aEventStatus,
+                                              nsresult* aRv);
+
     MOZ_CAN_RUN_SCRIPT
     nsresult RetargetEventToParent(WidgetGUIEvent* aGUIEvent,
                                    nsEventStatus* aEventStatus);
 
     /**
      * MaybeHandleEventWithAccessibleCaret() may handle aGUIEvent with
      * AccessibleCaretEventHub if it's necessary.
      *