Bug 815383 Handle shift, control, option and meta flags in NSFlagsChanged event handler even if some applications send it with device dependent flags but without proper keyCode r=smichaud
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 21 Dec 2012 17:31:24 +0900
changeset 125853 53accd955c2ba8ea558815a1b3dcb164416daf41
parent 125852 fe8429f81df86b5c4c2bd722490edcf2e99b8ac4
child 125854 706dc7c6be20327916dede75d98fd2cbeb85e2ff
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmichaud
bugs815383
milestone20.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 815383 Handle shift, control, option and meta flags in NSFlagsChanged event handler even if some applications send it with device dependent flags but without proper keyCode r=smichaud
widget/cocoa/TextInputHandler.mm
--- a/widget/cocoa/TextInputHandler.mm
+++ b/widget/cocoa/TextInputHandler.mm
@@ -1604,16 +1604,18 @@ TextInputHandler::HandleFlagsChanged(NSE
     case kVK_RightControl:
     case kVK_Option:
     case kVK_RightOption:
     case kVK_Help: {
       // We assume that at most one modifier is changed per event if the event
       // is caused by pressing or releasing a modifier key.
       bool isKeyDown = ([aNativeEvent modifierFlags] & diff) != 0;
       DispatchKeyEventForFlagsChanged(aNativeEvent, isKeyDown);
+      // XXX Some applications might send the event with incorrect device-
+      //     dependent flags.
       if (isKeyDown && ((diff & ~NSDeviceIndependentModifierFlagsMask) != 0)) {
         unsigned short keyCode = [aNativeEvent keyCode];
         ModifierKey* modifierKey = GetModifierKeyForDeviceDependentFlags(diff);
         if (modifierKey) {
           MOZ_ASSERT(modifierKey->keyCode == keyCode);
         } else {
           mModifierKeys.AppendElement(ModifierKey(diff, keyCode));
         }
@@ -1637,51 +1639,75 @@ TextInputHandler::HandleFlagsChanged(NSE
     default: {
       NSUInteger modifiers = sLastModifierState;
       for (int32_t bit = 0; bit < 32; ++bit) {
         NSUInteger flag = 1 << bit;
         if (!(diff & flag)) {
           continue;
         }
 
+        // Given correct information from the application, a flag change here
+        // will normally be a deactivation (except for some lockable modifiers
+        // such as CapsLock).  But some applications (like VNC) can send an
+        // activating event with a zero keyCode.  So we need to check for that
+        // here.
+        bool dispatchKeyDown = ((flag & [aNativeEvent modifierFlags]) != 0);
+
         unsigned short keyCode = 0;
-        bool dispatchKeyDown = false;
         if (flag & NSDeviceIndependentModifierFlagsMask) {
           switch (flag) {
             case NSAlphaShiftKeyMask:
               keyCode = kVK_CapsLock;
               dispatchKeyDown = true;
               break;
+
             case NSNumericPadKeyMask:
-              keyCode = kVK_ANSI_KeypadClear;
-              dispatchKeyDown = true;
-              break;
+              // NSNumericPadKeyMask is fired by VNC a lot. But not all of
+              // these events can really be Clear key events, so we just ignore
+              // them.
+              continue;
+
             case NSHelpKeyMask:
-              // NSHelpKeyMask change here must be a deactivation.
-              MOZ_ASSERT(!(flag & [aNativeEvent modifierFlags]));
               keyCode = kVK_Help;
               break;
+
             case NSFunctionKeyMask:
-              // NSFunctionKeyMask change here must be a deactivation.
-              MOZ_ASSERT(!(flag & [aNativeEvent modifierFlags]));
-              // We don't dispatch function key event for now.
+              // An NSFunctionKeyMask change here will normally be a
+              // deactivation.  But sometimes it will be an activation send (by
+              // VNC for example) with a zero keyCode.
               continue;
+
+            // These cases (NSShiftKeyMask, NSControlKeyMask, NSAlternateKeyMask
+            // and NSCommandKeyMask) should be handled by the other branch of
+            // the if statement, below (which handles device dependent flags).
+            // However, some applications (like VNC) can send key events without
+            // any device dependent flags, so we handle them here instead.
+            case NSShiftKeyMask:
+              keyCode = (modifiers & 0x0004) ? kVK_RightShift : kVK_Shift;
+              break;
+            case NSControlKeyMask:
+              keyCode = (modifiers & 0x2000) ? kVK_RightControl : kVK_Control;
+              break;
+            case NSAlternateKeyMask:
+              keyCode = (modifiers & 0x0040) ? kVK_RightOption : kVK_Option;
+              break;
+            case NSCommandKeyMask:
+              keyCode = (modifiers & 0x0010) ? kVK_RightCommand : kVK_Command;
+              break;
+
             default:
-              // The other cases (NSShiftKeyMask, NSControlKeyMask,
-              // NSAlternateKeyMask and NSCommandKeyMask) are handled by the
-              // other branch of the if statement, below (which handles device
-              // dependent flags).
               continue;
           }
         } else {
-          // Any modifier change here must be a deactivation.
-          MOZ_ASSERT(!(flag & [aNativeEvent modifierFlags]));
           ModifierKey* modifierKey =
             GetModifierKeyForDeviceDependentFlags(flag);
           if (!modifierKey) {
+            // See the note above (in the other branch of the if statement)
+            // about the NSShiftKeyMask, NSControlKeyMask, NSAlternateKeyMask
+            // and NSCommandKeyMask cases.
             continue;
           }
           keyCode = modifierKey->keyCode;
         }
 
         // Remove flags
         modifiers &= ~flag;
         switch (keyCode) {