Bug 1137572 part.7 Add TextEventDispatcherListener::WillDispatchKeyboardEvent() for easier to maintain r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 16 Mar 2016 13:47:48 +0900
changeset 328761 2982777d071d36ffa9761d4ec2347ff36640627c
parent 328760 5482d679c1a8b7c55657d50086f8eb6a59ef9ad9
child 328762 782cc1725295b36e34a854a4d64159da3b16f4e9
push id1146
push userCallek@gmail.com
push dateMon, 25 Jul 2016 16:35:44 +0000
treeherdermozilla-release@a55778f9cd5a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1137572
milestone48.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 1137572 part.7 Add TextEventDispatcherListener::WillDispatchKeyboardEvent() for easier to maintain r=smaug
dom/base/TextInputProcessor.cpp
dom/base/TextInputProcessor.h
widget/TextEventDispatcher.cpp
widget/TextEventDispatcher.h
widget/TextEventDispatcherListener.h
--- a/dom/base/TextInputProcessor.cpp
+++ b/dom/base/TextInputProcessor.cpp
@@ -700,16 +700,26 @@ TextInputProcessor::OnRemovedFrom(TextEv
   if (!mDispatcher) {
     return;
   }
   MOZ_ASSERT(aTextEventDispatcher == mDispatcher,
              "Wrong TextEventDispatcher notifies this");
   UnlinkFromTextEventDispatcher();
 }
 
+NS_IMETHODIMP_(void)
+TextInputProcessor::WillDispatchKeyboardEvent(
+                      TextEventDispatcher* aTextEventDispatcher,
+                      WidgetKeyboardEvent& aKeyboardEvent,
+                      uint32_t aIndexOfKeypress,
+                      void* aData)
+{
+  // TextInputProcessor doesn't set alternative char code.
+}
+
 nsresult
 TextInputProcessor::PrepareKeyboardEventToDispatch(
                       WidgetKeyboardEvent& aKeyboardEvent,
                       uint32_t aKeyFlags)
 {
   if (NS_WARN_IF(aKeyboardEvent.mCodeNameIndex == CODE_NAME_INDEX_USE_STRING)) {
     return NS_ERROR_INVALID_ARG;
   }
--- a/dom/base/TextInputProcessor.h
+++ b/dom/base/TextInputProcessor.h
@@ -31,16 +31,22 @@ public:
   NS_DECL_NSITEXTINPUTPROCESSOR
 
   // TextEventDispatcherListener
   NS_IMETHOD NotifyIME(TextEventDispatcher* aTextEventDispatcher,
                        const IMENotification& aNotification) override;
   NS_IMETHOD_(void)
     OnRemovedFrom(TextEventDispatcher* aTextEventDispatcher) override;
 
+  NS_IMETHOD_(void) WillDispatchKeyboardEvent(
+                      TextEventDispatcher* aTextEventDispatcher,
+                      WidgetKeyboardEvent& aKeyboardEvent,
+                      uint32_t aIndexOfKeypress,
+                      void* aData) override;
+
 protected:
   virtual ~TextInputProcessor();
 
 private:
   bool IsComposing() const;
   nsresult BeginInputTransactionInternal(
              mozIDOMWindow* aWindow,
              nsITextInputProcessorCallback* aCallback,
--- a/widget/TextEventDispatcher.cpp
+++ b/widget/TextEventDispatcher.cpp
@@ -367,26 +367,29 @@ TextEventDispatcher::NotifyIME(const IME
     }
   }
 }
 
 bool
 TextEventDispatcher::DispatchKeyboardEvent(
                        EventMessage aMessage,
                        const WidgetKeyboardEvent& aKeyboardEvent,
-                       nsEventStatus& aStatus)
+                       nsEventStatus& aStatus,
+                       void* aData)
 {
-  return DispatchKeyboardEventInternal(aMessage, aKeyboardEvent, aStatus);
+  return DispatchKeyboardEventInternal(aMessage, aKeyboardEvent, aStatus,
+                                       aData);
 }
 
 bool
 TextEventDispatcher::DispatchKeyboardEventInternal(
                        EventMessage aMessage,
                        const WidgetKeyboardEvent& aKeyboardEvent,
                        nsEventStatus& aStatus,
+                       void* aData,
                        uint32_t aIndexOfKeypress)
 {
   MOZ_ASSERT(aMessage == eKeyDown || aMessage == eKeyUp ||
              aMessage == eKeyPress, "Invalid aMessage value");
   nsresult rv = GetState();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return false;
   }
@@ -459,24 +462,39 @@ TextEventDispatcher::DispatchKeyboardEve
   } else {
     // If it's not a keyboard event for native key event, we should ensure that
     // mNativeKeyEvent and mPluginEvent are null/empty.
     keyEvent.mNativeKeyEvent = nullptr;
     keyEvent.mPluginEvent.Clear();
   }
   // TODO: Manage mUniqueId here.
 
+  // Request the alternative char codes for the key event.
+  // XXX Currently, they are necessary only when the event is eKeyPress.
+  keyEvent.alternativeCharCodes.Clear();
+  if (aMessage == eKeyPress &&
+      (keyEvent.IsControl() || keyEvent.IsAlt() ||
+       keyEvent.IsMeta() || keyEvent.IsOS())) {
+    nsCOMPtr<TextEventDispatcherListener> listener =
+      do_QueryReferent(mListener);
+    if (listener) {
+      listener->WillDispatchKeyboardEvent(this, keyEvent, aIndexOfKeypress,
+                                          aData);
+    }
+  }
+
   DispatchInputEvent(mWidget, keyEvent, aStatus);
   return true;
 }
 
 bool
 TextEventDispatcher::MaybeDispatchKeypressEvents(
                        const WidgetKeyboardEvent& aKeyboardEvent,
-                       nsEventStatus& aStatus)
+                       nsEventStatus& aStatus,
+                       void* aData)
 {
   // If the key event was consumed, keypress event shouldn't be fired.
   if (aStatus == nsEventStatus_eConsumeNoDefault) {
     return false;
   }
 
   // If the key isn't a printable key or just inputting one character or
   // no character, we should dispatch only one keypress.  Otherwise, i.e.,
@@ -486,17 +504,17 @@ TextEventDispatcher::MaybeDispatchKeypre
     aKeyboardEvent.mKeyNameIndex != KEY_NAME_INDEX_USE_STRING ?
       1 : std::max(static_cast<nsAString::size_type>(1),
                    aKeyboardEvent.mKeyValue.Length());
   bool isDispatched = false;
   bool consumed = false;
   for (size_t i = 0; i < keypressCount; i++) {
     aStatus = nsEventStatus_eIgnore;
     if (!DispatchKeyboardEventInternal(eKeyPress, aKeyboardEvent,
-                                       aStatus, i)) {
+                                       aStatus, aData, i)) {
       // The widget must have been gone.
       break;
     }
     isDispatched = true;
     if (!consumed) {
       consumed = (aStatus == nsEventStatus_eConsumeNoDefault);
     }
   }
--- a/widget/TextEventDispatcher.h
+++ b/widget/TextEventDispatcher.h
@@ -222,39 +222,47 @@ public:
    *                        Use MaybeDispatchKeypressEvents() for dispatching
    *                        eKeyPress.
    * @param aKeyboardEvent  A keyboard event.
    * @param aStatus         If dispatching event should be marked as consumed,
    *                        set nsEventStatus_eConsumeNoDefault.  Otherwise,
    *                        set nsEventStatus_eIgnore.  After dispatching
    *                        a event and it's consumed this returns
    *                        nsEventStatus_eConsumeNoDefault.
+   * @param aData           Calling this method may cause calling
+   *                        WillDispatchKeyboardEvent() of the listener.
+   *                        aData will be set to its argument.
    * @return                true if an event is dispatched.  Otherwise, false.
    */
   bool DispatchKeyboardEvent(EventMessage aMessage,
                              const WidgetKeyboardEvent& aKeyboardEvent,
-                             nsEventStatus& aStatus);
+                             nsEventStatus& aStatus,
+                             void* aData = nullptr);
 
   /**
    * MaybeDispatchKeypressEvents() maybe dispatches a keypress event which is
    * generated from aKeydownEvent.
    *
    * @param aKeyboardEvent  A keyboard event.
    * @param aStatus         Sets the result when the caller dispatches
    *                        aKeyboardEvent.  Note that if the value is
    *                        nsEventStatus_eConsumeNoDefault, this does NOT
    *                        dispatch keypress events.
    *                        When this method dispatches one or more keypress
    *                        events and one of them is consumed, this returns
    *                        nsEventStatus_eConsumeNoDefault.
+   * @param aData           Calling this method may cause calling
+   *                        WillDispatchKeyboardEvent() of the listener.
+   *                        aData will be set to its argument.
    * @return                true if one or more events are dispatched.
    *                        Otherwise, false.
    */
   bool MaybeDispatchKeypressEvents(const WidgetKeyboardEvent& aKeyboardEvent,
-                                   nsEventStatus& aStatus);
+                                   nsEventStatus& aStatus,
+                                   void* aData = nullptr);
 
 private:
   // mWidget is owner of the instance.  When this is created, this is set.
   // And when mWidget is released, this is cleared by OnDestroyWidget().
   // Note that mWidget may be destroyed already (i.e., mWidget->Destroyed() may
   // return true).
   nsIWidget* mWidget;
   // mListener is a weak reference to TextEventDispatcherListener.  That might
@@ -400,27 +408,31 @@ private:
    * @param aKeyboardEvent  A keyboard event.  If aMessage is eKeyPress and
    *                        the event is for second or later character, its
    *                        mKeyValue should be empty string.
    * @param aStatus         If dispatching event should be marked as consumed,
    *                        set nsEventStatus_eConsumeNoDefault.  Otherwise,
    *                        set nsEventStatus_eIgnore.  After dispatching
    *                        a event and it's consumed this returns
    *                        nsEventStatus_eConsumeNoDefault.
+   * @param aData           Calling this method may cause calling
+   *                        WillDispatchKeyboardEvent() of the listener.
+   *                        aData will be set to its argument.
    * @param aIndexOfKeypress    This must be 0 if aMessage isn't eKeyPress or
    *                            aKeyboard.mKeyNameIndex isn't
    *                            KEY_NAME_INDEX_USE_STRING.  Otherwise, i.e.,
    *                            when an eKeyPress event causes inputting
    *                            text, this must be between 0 and
    *                            mKeyValue.Length() - 1 since keypress events
    *                            sending only one character per event.
    * @return                true if an event is dispatched.  Otherwise, false.
    */
   bool DispatchKeyboardEventInternal(EventMessage aMessage,
                                      const WidgetKeyboardEvent& aKeyboardEvent,
                                      nsEventStatus& aStatus,
+                                     void* aData,
                                      uint32_t aIndexOfKeypress = 0);
 };
 
 } // namespace widget
 } // namespace mozilla
 
 #endif // #ifndef mozilla_widget_textcompositionsynthesizer_h_
--- a/widget/TextEventDispatcherListener.h
+++ b/widget/TextEventDispatcherListener.h
@@ -31,16 +31,58 @@ public:
                        const IMENotification& aNotification) = 0;
 
   /**
    * OnRemovedFrom() is called when the TextEventDispatcher stops working and
    * is releasing the listener.
    */
   NS_IMETHOD_(void) OnRemovedFrom(
                       TextEventDispatcher* aTextEventDispatcher) = 0;
+
+  /**
+   * WillDispatchKeyboardEvent() may be called immediately before
+   * TextEventDispatcher dispatching a keyboard event.  This is called only
+   * during calling TextEventDispatcher::DispatchKeyboardEvent() or
+   * TextEventDispatcher::MaybeDispatchKeypressEvents().  But this may not
+   * be called if TextEventDispatcher thinks that the keyboard event doesn't
+   * need alternative char codes.
+   *
+   * This method can overwrite any members of aKeyboardEvent which is already
+   * initialized by TextEventDispatcher.  If it's necessary, this method should
+   * overwrite the charCode when Control key is pressed.  TextEventDispatcher
+   * computes charCode from mKeyValue.  However, when Control key is pressed,
+   * charCode should be an ASCII char.  In such case, this method needs to
+   * overwrite it properly.
+   *
+   * @param aTextEventDispatcher    Pointer to the caller.
+   * @param aKeyboardEvent          The event trying to dispatch.
+   *                                This is already initialized, but if it's
+   *                                necessary, this method should overwrite the
+   *                                members and set alternative char codes.
+   * @param aIndexOfKeypress        When aKeyboardEvent is eKeyPress event,
+   *                                it may be a sequence of keypress events
+   *                                if the key causes multiple characters.
+   *                                In such case, this indicates the index from
+   *                                first keypress event.
+   *                                If aKeyboardEvent is the first eKeyPress or
+   *                                other events, this value is 0.
+   * @param aData                   The pointer which was specified at calling
+   *                                the method of TextEventDispatcher.
+   *                                For example, if you do:
+   *                                |TextEventDispatcher->DispatchKeyboardEvent(
+   *                                   eKeyDown, event, status, this);|
+   *                                Then, aData of this method becomes |this|.
+   *                                Finally, you can use it like:
+   *                                |static_cast<NativeEventHandler*>(aData)|
+   */
+  NS_IMETHOD_(void) WillDispatchKeyboardEvent(
+                      TextEventDispatcher* aTextEventDispatcher,
+                      WidgetKeyboardEvent& aKeyboardEvent,
+                      uint32_t aIndexOfKeypress,
+                      void* aData) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(TextEventDispatcherListener,
                               NS_TEXT_INPUT_PROXY_LISTENER_IID)
 
 } // namespace widget
 } // namespace mozilla