Bug 757688 part.8 Make sure test_keycodes.xul emulates correct key events r=jimm
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 15 Jun 2012 18:52:51 +0900
changeset 96822 c4b46347c04bd25be43d2cb4e71d11e574e0524e
parent 96821 f5b8c6a545cf633d50b390b07bbf3da3b79023d3
child 96823 3ec9d53ce65c61287e2d3991544a51f5686940b1
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjimm
bugs757688
milestone16.0a1
Bug 757688 part.8 Make sure test_keycodes.xul emulates correct key events r=jimm
widget/tests/test_keycodes.xul
widget/windows/nsWindow.cpp
--- a/widget/tests/test_keycodes.xul
+++ b/widget/tests/test_keycodes.xul
@@ -55,16 +55,24 @@ function synthesizeNativeKey(aLayout, aK
     if (aModifiers.capsLock) modifiers |= 0x01;
     if (aModifiers.numLock) modifiers |= 0x02;
     if (aModifiers.shift) modifiers |= 0x0100;
     if (aModifiers.shiftRight) modifiers |= 0x0200;
     if (aModifiers.ctrl) modifiers |= 0x0400;
     if (aModifiers.ctrlRight) modifiers |= 0x0800;
     if (aModifiers.alt) modifiers |= 0x1000;
     if (aModifiers.altRight) modifiers |= 0x2000;
+    if (IS_WIN && aModifiers.altGr) {
+      if (!aModifiers.ctrl && !aModifiers.ctrlRight) {
+        modifiers |= 0x0400;
+      }
+      if (!aModifiers.alt && !aModifiers.altRight) {
+        modifiers |= 0x1000;
+      }
+    }
     if (aModifiers.command) modifiers |= 0x4000;
     if (aModifiers.commandRight) modifiers |= 0x8000;
     if (aModifiers.help) modifiers |= 0x10000;
     if (aModifiers.function) modifiers |= 0x100000;
     if (aModifiers.numericKeyPad) modifiers |= 0x01000000;
 
     utils.sendNativeKeyEvent(aLayout, aKeyCode, modifiers,
                              aSystemChars, aSystemUnmodifiedChars);
@@ -170,46 +178,79 @@ function runKeyEventTests()
         keyUpFlags &= ~aFlag;
         return oldValue != keyUpFlags;
       }
       return false;
     }
 
     function isStateChangingModifierKeyEvent(e)
     {
+      var flags = 0;
+      if (e.type == "keydown") {
+        flags = keyDownFlags ^ keyUpFlags;
+      } else if (e.type == "keyup") {
+        flags = keyUpFlags;
+      }
       switch (e.keyCode) {
         case e.DOM_VK_SHIFT:
+          is(e.ctrlKey, (flags & kCtrlFlag) != 0, name + ", Ctrl of Shift " + e.type + " event mismatch");
+          is(e.metaKey, (flags & kMetaFlag) != 0, name + ", Command of Shift " + e.type + " event mismatch");
+          is(e.altKey, (flags & kAltFlag) != 0, name + ", Alt of Shift " + e.type + " event mismatch");
+          is(e.shiftKey, e.type == "keydown", name + ", Shift of Shift " + e.type + " event mismatch");
           return (testingEvent.shift || testingEvent.shiftRight) && removeFlag(e, kShiftFlag);
         case e.DOM_VK_CONTROL:
-          return (testingEvent.ctrl || testingEvent.ctrlRight) && removeFlag(e, kCtrlFlag);
+          is(e.ctrlKey, e.type == "keydown", name + ", Ctrl of Ctrl " + e.type + " event mismatch");
+          is(e.metaKey, (flags & kMetaFlag) != 0, name + ", Command of Ctrl " + e.type + " event mismatch");
+          is(e.altKey, (flags & kAltFlag) != 0, name + ", Alt of Ctrl " + e.type + " event mismatch");
+          is(e.shiftKey, (flags & kShiftFlag) != 0, name + ", Shift of Ctrl " + e.type + " event mismatch");
+          return (testingEvent.ctrl || testingEvent.ctrlRight || (IS_WIN && testingEvent.altGr)) && removeFlag(e, kCtrlFlag);
         case e.DOM_VK_ALT:
-          return (testingEvent.alt || testingEvent.altRight) && removeFlag(e, kAltFlag);
+          is(e.ctrlKey, (flags & kCtrlFlag) != 0, name + ", Ctrl of Alt " + e.type + " event mismatch");
+          is(e.metaKey, (flags & kMetaFlag) != 0, name + ", Command of Alt " + e.type + " event mismatch");
+          is(e.altKey, e.type == "keydown", name + ", Alt of Alt " + e.type + " event mismatch");
+          is(e.shiftKey, (flags & kShiftFlag) != 0, name + ", Shift of Alt " + e.type + " event mismatch");
+          return (testingEvent.alt || testingEvent.altRight || (IS_WIN && testingEvent.altGr)) && removeFlag(e, kAltFlag);
         case e.DOM_VK_META:
+          is(e.ctrlKey, (flags & kCtrlFlag) != 0, name + ", Ctrl of Command " + e.type + " evnet mismatch");
+          is(e.metaKey, e.type == "keydown", name + ", Command of Command " + e.type + " evnet mismatch");
+          is(e.altKey, (flags & kAltFlag) != 0, name + ", Alt of Command " + e.type + " evnet mismatch");
+          is(e.shiftKey, (flags & kShiftFlag) != 0, name + ", Shift of Command " + e.type + " evnet mismatch");
           return testingEvent.command && removeFlag(e, kMetaFlag);
         case e.DOM_VK_NUM_LOCK:
+          is(e.ctrlKey, (flags & kCtrlFlag) != 0, name + ", Ctrl of NumLock " + e.type + " event mismatch");
+          is(e.metaKey, (flags & kMetaFlag) != 0, name + ", Command of NumLock " + e.type + " event mismatch");
+          is(e.altKey, (flags & kAltFlag) != 0, name + ", Alt of NumLock " + e.type + " event mismatch");
+          is(e.shiftKey, (flags & kShiftFlag) != 0, name + ", Shift of NumLock " + e.type + " event mismatch");
           return testingEvent.numLock && removeFlag(e, kNumLockFlag);
         case e.DOM_VK_CAPS_LOCK:
+          is(e.ctrlKey, (flags & kCtrlFlag) != 0, name + ", Ctrl of CapsLock " + e.type + " event mismatch");
+          is(e.metaKey, (flags & kMetaFlag) != 0, name + ", Command of CapsLock " + e.type + " event mismatch");
+          is(e.altKey, (flags & kAltFlag) != 0, name + ", Alt of CapsLock " + e.type + " event mismatch");
+          is(e.shiftKey, (flags & kShiftFlag) != 0, name + ", Shift of CapsLock " + e.type + " event mismatch");
           return testingEvent.capsLock && removeFlag(e, kCapsLockFlag);
       }
       return false;
     }
 
     // Ignore the state changing key events which is fired by the testing event.
     if (!isStateChangingModifierKeyEvent(e))
       eventList.push(e);
     e.preventDefault();
   }
 
   const SHOULD_DELIVER_NONE             = 0x0;
   const SHOULD_DELIVER_KEYDOWN          = 0x1;
   const SHOULD_DELIVER_KEYPRESS         = 0x2;
   const SHOULD_DELIVER_KEYUP            = 0x4;
+  const SHOULD_NOT_CAUSE_INPUT          = 0x8;
   const SHOULD_DELIVER_ALL              = SHOULD_DELIVER_KEYDOWN |
                                           SHOULD_DELIVER_KEYPRESS |
                                           SHOULD_DELIVER_KEYUP;
+  const SHOULD_DELIVER_ALL_BUT_NOT_CAUSE_INPUT = SHOULD_DELIVER_ALL |
+                                          SHOULD_NOT_CAUSE_INPUT;
   const SHOULD_DELIVER_KEYDOWN_KEYUP    = SHOULD_DELIVER_KEYDOWN |
                                           SHOULD_DELIVER_KEYUP;
   const SHOULD_DELIVER_KEYDOWN_KEYPRESS = SHOULD_DELIVER_KEYDOWN |
                                           SHOULD_DELIVER_KEYPRESS;
 
   // The first parameter is the complete input event. The second parameter is
   // what to test against. The third parameter is which key events should be
   // delived for the event.
@@ -222,19 +263,19 @@ function runKeyEventTests()
     // The modifier key events which are fired for state changing are har to
     // test. We should ignore them for now.
     keyDownFlags = keyUpFlags = 0;
     if (!IS_MAC) {
       // On Mac, nsChildView doesn't generate modifier keydown/keyup events for
       // state changing for synthesizeNativeKeyEvent.
       if (aEvent.shift || aEvent.shiftRight)
         keyDownFlags |= kShiftFlag;
-      if (aEvent.ctrl || aEvent.ctrlRight || aEvent.altGr)
+      if (aEvent.ctrl || aEvent.ctrlRight || (IS_WIN && aEvent.altGr))
         keyDownFlags |= kCtrlFlag;
-      if (aEvent.alt || aEvent.altRight || aEvent.altGr)
+      if (aEvent.alt || aEvent.altRight || (IS_WIN && aEvent.altGr))
         keyDownFlags |= kAltFlag;
       if (aEvent.command)
         keyDownFlags |= kMetaFlag;
       if (aEvent.numLock)
         keyDownFlags |= kNumLockFlag;
       if (aEvent.capsLock)
         keyDownFlags |= kCapsLockFlag;
       keyUpFlags = keyDownFlags;
@@ -266,20 +307,28 @@ function runKeyEventTests()
       var expectEventType = i < expectEventTypeList.length ? expectEventTypeList[i] : "";
       if (firedEventType != "")
         is(firedEventType, expectEventType, name + ", wrong type event fired");
       else
         is(firedEventType, expectEventType, name + ", a needed event is not fired");
 
       if (firedEventType != "") {
         var e = eventList[i];
-        is(e.ctrlKey, aEvent.ctrl || aEvent.ctrlRight || 0, name + ", Ctrl mismatch");
-        is(e.metaKey, aEvent.command || aEvent.commandRight || 0, name + ", Command mismatch");
-        is(e.altKey, aEvent.alt || aEvent.altRight || 0, name + ", Alt mismatch");
-        is(e.shiftKey, aEvent.shift || aEvent.shiftRight || 0, name + ", Shift mismatch");
+        if (e.type == "keypress") {
+          var isCtrlExpected = aEvent.ctrl || aEvent.ctrlRight || false;
+          var isAltExpected = aEvent.alt || aEvent.altRight || false;
+          if (IS_WIN && aEvent.altGr) {
+            isCtrlExpected = isAltExpected =
+              ((aShouldDelivedEvent & SHOULD_NOT_CAUSE_INPUT) != 0);
+          }
+          is(e.ctrlKey, isCtrlExpected, name + ", Ctrl mismatch");
+          is(e.metaKey, aEvent.command || aEvent.commandRight || false, name + ", Command mismatch");
+          is(e.altKey, isAltExpected, name + ", Alt mismatch");
+          is(e.shiftKey, aEvent.shift || aEvent.shiftRight || false, name + ", Shift mismatch");
+        }
 
         if (aExpectGeckoChar.length > 0 && e.type == "keypress") {
           is(e.charCode, aExpectGeckoChar.charCodeAt(keypressCount++), name + ", charcode");
           if (aExpectedGeckoKeyCode >= 0) {
             if (aExpectGeckoChar) {
               is(e.keyCode, 0, name + ", wrong keycode");
             } else {
               is(e.keyCode, aExpectedGeckoKeyCode, name + ", wrong keycode");
@@ -1589,54 +1638,34 @@ function runKeyEventTests()
     testKey({layout:"US", keyCode:192, chars:"`"},
             nsIDOMKeyEvent.DOM_VK_BACK_QUOTE, "`", SHOULD_DELIVER_ALL);
     testKey({layout:"US", keyCode:192, shift:1, chars:"~"},
             nsIDOMKeyEvent.DOM_VK_BACK_QUOTE, "~", SHOULD_DELIVER_ALL);
 
     // Numpad
     testKey({layout:"US", keyCode:96, numLock:1, chars:"0"},
             nsIDOMKeyEvent.DOM_VK_NUMPAD0, "0", SHOULD_DELIVER_ALL);
-    testKey({layout:"US", keyCode:96, numLock:1, shift:1, chars:"0"},
-            nsIDOMKeyEvent.DOM_VK_NUMPAD0, "0", SHOULD_DELIVER_ALL);
     testKey({layout:"US", keyCode:97, numLock:1, chars:"1"},
             nsIDOMKeyEvent.DOM_VK_NUMPAD1, "1", SHOULD_DELIVER_ALL);
-    testKey({layout:"US", keyCode:97, numLock:1, shift:1, chars:"1"},
-            nsIDOMKeyEvent.DOM_VK_NUMPAD1, "1", SHOULD_DELIVER_ALL);
     testKey({layout:"US", keyCode:98, numLock:1, chars:"2"},
             nsIDOMKeyEvent.DOM_VK_NUMPAD2, "2", SHOULD_DELIVER_ALL);
-    testKey({layout:"US", keyCode:98, numLock:1, shift:1, chars:"2"},
-            nsIDOMKeyEvent.DOM_VK_NUMPAD2, "2", SHOULD_DELIVER_ALL);
     testKey({layout:"US", keyCode:99, numLock:1, chars:"3"},
             nsIDOMKeyEvent.DOM_VK_NUMPAD3, "3", SHOULD_DELIVER_ALL);
-    testKey({layout:"US", keyCode:99, numLock:1, shift:1, chars:"3"},
-            nsIDOMKeyEvent.DOM_VK_NUMPAD3, "3", SHOULD_DELIVER_ALL);
     testKey({layout:"US", keyCode:100, numLock:1, chars:"4"},
             nsIDOMKeyEvent.DOM_VK_NUMPAD4, "4", SHOULD_DELIVER_ALL);
-    testKey({layout:"US", keyCode:100, numLock:1, shift:1, chars:"4"},
-            nsIDOMKeyEvent.DOM_VK_NUMPAD4, "4", SHOULD_DELIVER_ALL);
     testKey({layout:"US", keyCode:101, numLock:1, chars:"5"},
             nsIDOMKeyEvent.DOM_VK_NUMPAD5, "5", SHOULD_DELIVER_ALL);
-    testKey({layout:"US", keyCode:101, numLock:1, shift:1, chars:"5"},
-            nsIDOMKeyEvent.DOM_VK_NUMPAD5, "5", SHOULD_DELIVER_ALL);
     testKey({layout:"US", keyCode:102, numLock:1, chars:"6"},
             nsIDOMKeyEvent.DOM_VK_NUMPAD6, "6", SHOULD_DELIVER_ALL);
-    testKey({layout:"US", keyCode:102, numLock:1, shift:1, chars:"6"},
-            nsIDOMKeyEvent.DOM_VK_NUMPAD6, "6", SHOULD_DELIVER_ALL);
     testKey({layout:"US", keyCode:103, numLock:1, chars:"7"},
             nsIDOMKeyEvent.DOM_VK_NUMPAD7, "7", SHOULD_DELIVER_ALL);
-    testKey({layout:"US", keyCode:103, numLock:1, shift:1, chars:"7"},
-            nsIDOMKeyEvent.DOM_VK_NUMPAD7, "7", SHOULD_DELIVER_ALL);
     testKey({layout:"US", keyCode:104, numLock:1, chars:"8"},
             nsIDOMKeyEvent.DOM_VK_NUMPAD8, "8", SHOULD_DELIVER_ALL);
-    testKey({layout:"US", keyCode:104, numLock:1, shift:1, chars:"8"},
-            nsIDOMKeyEvent.DOM_VK_NUMPAD8, "8", SHOULD_DELIVER_ALL);
     testKey({layout:"US", keyCode:105, numLock:1, chars:"9"},
             nsIDOMKeyEvent.DOM_VK_NUMPAD9, "9", SHOULD_DELIVER_ALL);
-    testKey({layout:"US", keyCode:105, numLock:1, shift:1, chars:"9"},
-            nsIDOMKeyEvent.DOM_VK_NUMPAD9, "9", SHOULD_DELIVER_ALL);
 
     testKey({layout:"US", keyCode:106, numLock:1, chars:"*"},
             nsIDOMKeyEvent.DOM_VK_MULTIPLY, "*", SHOULD_DELIVER_ALL);
     testKey({layout:"US", keyCode:106, numLock:1, shift:1, chars:"*"},
             nsIDOMKeyEvent.DOM_VK_MULTIPLY, "*", SHOULD_DELIVER_ALL);
     testKey({layout:"US", keyCode:107, numLock:1, chars:"+"},
             nsIDOMKeyEvent.DOM_VK_ADD, "+", SHOULD_DELIVER_ALL);
     testKey({layout:"US", keyCode:107, numLock:1, shift:1, chars:"+"},
@@ -1827,20 +1856,20 @@ function runKeyEventTests()
     testKey({layout:"French", keyCode:192, capsLock:1, chars:"%"},
             nsIDOMKeyEvent.DOM_VK_PERCENT, "%", SHOULD_DELIVER_ALL);
     testKey({layout:"French", keyCode:192, capsLock:1, shift:1, chars:"\u00F9"},
             nsIDOMKeyEvent.DOM_VK_PERCENT, "\u00F9", SHOULD_DELIVER_ALL);
     testKey({layout:"French", keyCode:220, capsLock:1, chars:"\u00B5"},
             nsIDOMKeyEvent.DOM_VK_ASTERISK, "\u00B5", SHOULD_DELIVER_ALL);
     testKey({layout:"French", keyCode:220, capsLock:1, shift:1, chars:"*"},
             nsIDOMKeyEvent.DOM_VK_ASTERISK, "*", SHOULD_DELIVER_ALL);
-    testKey({layout:"French", keyCode:226, capsLock:1, chars:">"},
+    testKey({layout:"French", keyCode:226, capsLock:1, chars:"<"},
+            nsIDOMKeyEvent.DOM_VK_LESS_THAN, "<", SHOULD_DELIVER_ALL);
+    testKey({layout:"French", keyCode:226, capsLock:1, shift:1, chars:">"},
             nsIDOMKeyEvent.DOM_VK_LESS_THAN, ">", SHOULD_DELIVER_ALL);
-    testKey({layout:"French", keyCode:226, capsLock:1, shift:1, chars:"<"},
-            nsIDOMKeyEvent.DOM_VK_LESS_THAN, "<", SHOULD_DELIVER_ALL);
     testKey({layout:"French", keyCode:188, capsLock:1, chars:"?"},
             nsIDOMKeyEvent.DOM_VK_COMMA, "?", SHOULD_DELIVER_ALL);
     testKey({layout:"French", keyCode:188, capsLock:1, shift:1, chars:","},
             nsIDOMKeyEvent.DOM_VK_COMMA, ",", SHOULD_DELIVER_ALL);
     testKey({layout:"French", keyCode:190, capsLock:1, chars:"."},
             nsIDOMKeyEvent.DOM_VK_SEMICOLON, ".", SHOULD_DELIVER_ALL);
     testKey({layout:"French", keyCode:190, capsLock:1, shift:1, chars:";"},
             nsIDOMKeyEvent.DOM_VK_SEMICOLON, ";", SHOULD_DELIVER_ALL);
@@ -1852,17 +1881,17 @@ function runKeyEventTests()
             nsIDOMKeyEvent.DOM_VK_EXCLAMATION, "\u00A7", SHOULD_DELIVER_ALL);
     testKey({layout:"French", keyCode:223, capsLock:1, shift:1, chars:"!"},
             nsIDOMKeyEvent.DOM_VK_EXCLAMATION, "!", SHOULD_DELIVER_ALL);
 
     // AltGr
     testKey({layout:"French", keyCode:48, altGr:1, chars:"@"},
             nsIDOMKeyEvent.DOM_VK_0, "@", SHOULD_DELIVER_ALL);
     testKey({layout:"French", keyCode:49, altGr:1, chars:""},
-            nsIDOMKeyEvent.DOM_VK_1, "", SHOULD_DELIVER_KEYDOWN_KEYUP);
+            nsIDOMKeyEvent.DOM_VK_1, "&", SHOULD_DELIVER_ALL_BUT_NOT_CAUSE_INPUT);
     //testKey({layout:"French", keyCode:50, altGr:1, chars:""},
     //        nsIDOMKeyEvent.DOM_VK_2, "2", SHOULD_DELIVER_ALL); // Dead-key
     testKey({layout:"French", keyCode:51, altGr:1, chars:"#"},
             nsIDOMKeyEvent.DOM_VK_3, "#", SHOULD_DELIVER_ALL);
     testKey({layout:"French", keyCode:52, altGr:1, chars:"{"},
             nsIDOMKeyEvent.DOM_VK_4, "{", SHOULD_DELIVER_ALL);
     testKey({layout:"French", keyCode:53, altGr:1, chars:"["},
             nsIDOMKeyEvent.DOM_VK_5, "[", SHOULD_DELIVER_ALL);
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -6405,16 +6405,35 @@ LRESULT nsWindow::OnKeyDown(const MSG &a
   else if (gotMsg &&
            (aFakeCharMessage ||
             msg.message == WM_CHAR || msg.message == WM_SYSCHAR || msg.message == WM_DEADCHAR)) {
     if (aFakeCharMessage) {
       MSG msg = aFakeCharMessage->GetCharMessage(mWnd);
       if (msg.message == WM_DEADCHAR) {
         return false;
       }
+#ifdef DEBUG
+      if (KeyboardLayout::IsPrintableCharKey(virtualKeyCode)) {
+        nsPrintfCString log(
+          "virtualKeyCode=0x%02X, inputtingChar={ mChars=[ 0x%04X, 0x%04X, "
+          "0x%04X, 0x%04X, 0x%04X ], mLength=%d }, wParam=0x%04X",
+          virtualKeyCode, inputtingChars.mChars[0], inputtingChars.mChars[1],
+          inputtingChars.mChars[2], inputtingChars.mChars[3],
+          inputtingChars.mChars[4], inputtingChars.mLength, msg.wParam);
+        if (!inputtingChars.mLength) {
+          log.Insert("length is zero: ", 0);
+          NS_ERROR(log.get());
+          NS_ABORT();
+        } else if (inputtingChars.mChars[0] != msg.wParam) {
+          log.Insert("character mismatch: ", 0);
+          NS_ERROR(log.get());
+          NS_ABORT();
+        }
+      }
+#endif // #ifdef DEBUG
       return OnChar(msg, nativeKey, aModKeyState, nsnull, extraFlags);
     }
 
     // If prevent default set for keydown, do same for keypress
     ::GetMessageW(&msg, mWnd, msg.message, msg.message);
 
     if (msg.message == WM_DEADCHAR) {
       if (!PluginHasFocus())