Bug 685073 part.2 Consume key event which causes nested key event r=smichaud
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 30 Sep 2011 15:17:33 +0900
changeset 77905 e734bd300268
parent 77904 9c0aad93edc4
child 77906 10298b25af4e
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewerssmichaud
bugs685073
milestone10.0a1
Bug 685073 part.2 Consume key event which causes nested key event r=smichaud
widget/src/cocoa/TextInputHandler.h
widget/src/cocoa/TextInputHandler.mm
--- a/widget/src/cocoa/TextInputHandler.h
+++ b/widget/src/cocoa/TextInputHandler.h
@@ -476,30 +476,33 @@ protected:
     // Handling native key event
     NSEvent* mKeyEvent;
     // Whether keydown event was consumed by web contents or chrome contents.
     bool mKeyDownHandled;
     // Whether keypress event was dispatched for mKeyEvent.
     bool mKeyPressDispatched;
     // Whether keypress event was consumed by web contents or chrome contents.
     bool mKeyPressHandled;
+    // Whether the key event causes other key events via IME or something.
+    bool mCausedOtherKeyEvents;
 
     KeyEventState(NSEvent* aNativeKeyEvent) : mKeyEvent(nsnull)
     {
       Clear();
       Set(aNativeKeyEvent);
     }
 
     KeyEventState(const KeyEventState &aOther) : mKeyEvent(nsnull)
     {
       Clear();
       mKeyEvent = [aOther.mKeyEvent retain];
       mKeyDownHandled = aOther.mKeyDownHandled;
       mKeyPressDispatched = aOther.mKeyPressDispatched;
       mKeyPressHandled = aOther.mKeyPressHandled;
+      mCausedOtherKeyEvents = aOther.mCausedOtherKeyEvents;
     }
 
     ~KeyEventState()
     {
       Clear();
     }
 
     void Set(NSEvent* aNativeKeyEvent)
@@ -513,16 +516,17 @@ protected:
     {
       if (mKeyEvent) {
         [mKeyEvent release];
         mKeyEvent = nsnull;
       }
       mKeyDownHandled = PR_FALSE;
       mKeyPressDispatched = PR_FALSE;
       mKeyPressHandled = PR_FALSE;
+      mCausedOtherKeyEvents = PR_FALSE;
     }
 
     bool KeyDownOrPressHandled()
     {
       return mKeyDownHandled || mKeyPressHandled;
     }
 
   protected:
@@ -559,16 +563,22 @@ protected:
    */
   nsTArray<KeyEventState> mCurrentKeyEvents;
 
   /**
    *
    */
   KeyEventState* PushKeyEvent(NSEvent* aNativeKeyEvent)
   {
+    PRUint32 nestCount = mCurrentKeyEvents.Length();
+    for (PRUint32 i = 0; i < nestCount; i++) {
+      // When the key event is caused by another key event, all key events
+      // which are being handled should be marked as "consumed".
+      mCurrentKeyEvents[i].mCausedOtherKeyEvents = PR_TRUE;
+    }
     KeyEventState keyEventState(aNativeKeyEvent);
     return mCurrentKeyEvents.InsertElementAt(0, keyEventState);
   }
 
   /**
    * GetCurrentKeyEvent() returns current processing key event.
    */
   KeyEventState* GetCurrentKeyEvent()
--- a/widget/src/cocoa/TextInputHandler.mm
+++ b/widget/src/cocoa/TextInputHandler.mm
@@ -1119,17 +1119,18 @@ TextInputHandler::HandleKeyDownEvent(NSE
     // 1. If key events were nested during calling interpretKeyEvents, it means
     //    that IME did something.  Then, we should do nothing.
     // 2. If one or more commands are called like "deleteBackward", we should
     //    dispatch keypress event at that time.  Note that the command may have
     //    been a converted or generated action by IME.  Then, we shouldn't do
     //    our default action for this key.
     if (!(interpretKeyEventsCalled &&
           IsNormalCharInputtingEvent(keypressEvent))) {
-      if (currentKeyEvent->mKeyDownHandled) {
+      if (currentKeyEvent->mKeyDownHandled ||
+          currentKeyEvent->mCausedOtherKeyEvents) {
         keypressEvent.flags |= NS_EVENT_FLAG_NO_DEFAULT;
       }
       currentKeyEvent->mKeyPressHandled = DispatchEvent(keypressEvent);
       PR_LOG(gLog, PR_LOG_ALWAYS,
         ("%p TextInputHandler::HandleKeyDownEvent, keypress event dispatched",
          this));
     }
   }
@@ -1414,22 +1415,26 @@ TextInputHandler::InsertText(NSAttribute
 
 bool
 TextInputHandler::DoCommandBySelector(const char* aSelector)
 {
   KeyEventState* currentKeyEvent = GetCurrentKeyEvent();
 
   PR_LOG(gLog, PR_LOG_ALWAYS,
     ("%p TextInputHandler::DoCommandBySelector, aSelector=\"%s\", "
-     "Destroyed()=%s, keypressHandled=%s",
+     "Destroyed()=%s, keypressHandled=%s, causedOtherKeyEvents=%s",
      this, aSelector ? aSelector : "", TrueOrFalse(Destroyed()),
      currentKeyEvent ?
-       TrueOrFalse(currentKeyEvent->mKeyPressHandled) : "N/A"));
-
-  return !Destroyed() && currentKeyEvent && currentKeyEvent->mKeyPressHandled;
+       TrueOrFalse(currentKeyEvent->mKeyPressHandled) : "N/A",
+     currentKeyEvent ?
+       TrueOrFalse(currentKeyEvent->mCausedOtherKeyEvents) : "N/A"));
+
+  return !Destroyed() && currentKeyEvent &&
+         (currentKeyEvent->mKeyPressHandled ||
+          currentKeyEvent->mCausedOtherKeyEvents);
 }
 
 
 #pragma mark -
 
 
 /******************************************************************************
  *