Bug 619519 - Fix android key down/press/up handling, r=masayuki a=blocking-fennec
authorMichael Wu <mwu@mozilla.com>
Tue, 21 Dec 2010 14:36:28 -0800
changeset 59574 a2a3a6e8b0e0e1351ed92658583aa3c7ed1e441f
parent 59573 5ff3997a30c282edef635b58255dfaf6a1691a00
child 59575 95bbe1076dcb873cfed98fc30356bcc87a797b71
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersmasayuki, blocking-fennec
bugs619519
milestone2.0b9pre
Bug 619519 - Fix android key down/press/up handling, r=masayuki a=blocking-fennec
embedding/android/GeckoEvent.java
widget/src/android/AndroidJavaWrappers.cpp
widget/src/android/nsWindow.cpp
--- a/embedding/android/GeckoEvent.java
+++ b/embedding/android/GeckoEvent.java
@@ -125,16 +125,17 @@ public class GeckoEvent {
         mUnicodeChar = k.getUnicodeChar();
         mCharacters = k.getCharacters();
     }
 
     public GeckoEvent(MotionEvent m) {
         mType = MOTION_EVENT;
         mAction = m.getAction();
         mTime = m.getEventTime();
+        mMetaState = m.getMetaState();
         mP0 = new Point((int)m.getX(0), (int)m.getY(0));
         mCount = m.getPointerCount();
         if (mCount > 1)
             mP1 = new Point((int)m.getX(1), (int)m.getY(1));
     }
 
     public GeckoEvent(SensorEvent s) {
         mType = SENSOR_EVENT;
--- a/widget/src/android/AndroidJavaWrappers.cpp
+++ b/widget/src/android/AndroidJavaWrappers.cpp
@@ -291,16 +291,17 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jo
             mFlags = jenv->GetIntField(jobj, jFlagsField);
             mKeyCode = jenv->GetIntField(jobj, jKeyCodeField);
             mUnicodeChar = jenv->GetIntField(jobj, jUnicodeCharField);
             ReadCharactersField(jenv);
             break;
 
         case MOTION_EVENT:
             mTime = jenv->GetLongField(jobj, jTimeField);
+            mMetaState = jenv->GetIntField(jobj, jMetaStateField);
             mCount = jenv->GetIntField(jobj, jCountField);
             ReadP0Field(jenv);
             if (mCount > 1)
                 ReadP1Field(jenv);
             break;
 
         case IME_EVENT:
             if (mAction == IME_GET_TEXT || mAction == IME_SET_SELECTION) {
--- a/widget/src/android/nsWindow.cpp
+++ b/widget/src/android/nsWindow.cpp
@@ -115,20 +115,16 @@ class ContentCreationNotifier : public n
         return NS_OK;
     }
 };
 
 NS_IMPL_ISUPPORTS1(ContentCreationNotifier,
                    nsIObserver)
 #endif
 
-static PRBool gLeftShift;
-static PRBool gRightShift;
-static PRBool gLeftAlt;
-static PRBool gRightAlt;
 static PRBool gMenu;
 static PRBool gMenuConsumed;
 
 // All the toplevel windows that have been created; these are in
 // stacking order, so the window at gAndroidBounds[0] is the topmost
 // one.
 static nsTArray<nsWindow*> gTopLevelWindows;
 static nsWindow* gFocusedWindow = nsnull;
@@ -1123,20 +1119,20 @@ nsWindow::OnMotionEvent(AndroidGeckoEven
 send_again:
 
     nsMouseEvent event(PR_TRUE,
                        msg, this,
                        nsMouseEvent::eReal, nsMouseEvent::eNormal);
     InitEvent(event, &pt);
 
     event.time = ae->Time();
-    event.isShift = gLeftShift || gRightShift;
+    event.isShift = !!(ae->MetaState() & AndroidKeyEvent::META_SHIFT_ON);
     event.isControl = PR_FALSE;
     event.isMeta = PR_FALSE;
-    event.isAlt = gLeftAlt || gRightAlt;
+    event.isAlt = !!(ae->MetaState() & AndroidKeyEvent::META_ALT_ON);
 
     // XXX can we synthesize different buttons?
     event.button = nsMouseEvent::eLeftButton;
 
     if (msg != NS_MOUSE_MOVE)
         event.clickCount = 1;
 
     // XXX add the double-click handling logic here
@@ -1229,20 +1225,20 @@ void nsWindow::OnMultitouchEvent(Android
 }
 
 void
 nsWindow::DispatchGestureEvent(PRUint32 msg, PRUint32 direction, double delta,
                                const nsIntPoint &refPoint, PRUint64 time)
 {
     nsSimpleGestureEvent event(PR_TRUE, msg, this, direction, delta);
 
-    event.isShift = gLeftShift || gRightShift;
+    event.isShift = PR_FALSE;
     event.isControl = PR_FALSE;
     event.isMeta = PR_FALSE;
-    event.isAlt = gLeftAlt || gRightAlt;
+    event.isAlt = PR_FALSE;
     event.time = time;
     event.refPoint = refPoint;
 
     DispatchEvent(&event);
 }
 
 void
 nsWindow::InitKeyEvent(nsKeyEvent& event, AndroidGeckoEvent& key)
@@ -1395,20 +1391,26 @@ nsWindow::InitKeyEvent(nsKeyEvent& event
     case AndroidKeyEvent::KEYCODE_MEDIA_FAST_FORWARD:
     case AndroidKeyEvent::KEYCODE_MUTE:
         break;
     default:
         ALOG("Unknown key code!");
         break;
     }
 
-    event.charCode = key.UnicodeChar();
-    event.isShift = gLeftShift || gRightShift;
+    // Android gives us \n, so filter out some control characters.
+    if (event.message == NS_KEY_PRESS &&
+        key.UnicodeChar() >= ' ') {
+        event.charCode = key.UnicodeChar();
+        if (key.UnicodeChar())
+            event.keyCode = 0;
+    }
+    event.isShift = !!(key.MetaState() & AndroidKeyEvent::META_SHIFT_ON);
     event.isControl = gMenu;
-    event.isAlt = PR_FALSE;
+    event.isAlt = !!(key.MetaState() & AndroidKeyEvent::META_ALT_ON);
     event.isMeta = PR_FALSE;
     event.time = key.Time();
 
     if (gMenu)
         gMenuConsumed = PR_TRUE;
 }
 
 void
@@ -1490,51 +1492,50 @@ nsWindow::OnKeyEvent(AndroidGeckoEvent *
             DispatchEvent(&event);
         }
         return;
     default:
         ALOG("Unknown key action event!");
         return;
     }
 
-    PRBool isDown = ae->Action() == AndroidKeyEvent::ACTION_DOWN;
+    bool firePress = ae->Action() == AndroidKeyEvent::ACTION_DOWN;
     switch (ae->KeyCode()) {
     case AndroidKeyEvent::KEYCODE_SHIFT_LEFT:
-        gLeftShift = isDown;
-        break;
     case AndroidKeyEvent::KEYCODE_SHIFT_RIGHT:
-        gRightShift = isDown;
-        break;
     case AndroidKeyEvent::KEYCODE_ALT_LEFT:
-        gLeftAlt = isDown;
-        break;
     case AndroidKeyEvent::KEYCODE_ALT_RIGHT:
-        gRightAlt = isDown;
+        firePress = false;
         break;
     case AndroidKeyEvent::KEYCODE_BACK:
     case AndroidKeyEvent::KEYCODE_MENU:
     case AndroidKeyEvent::KEYCODE_SEARCH:
     case AndroidKeyEvent::KEYCODE_VOLUME_UP:
     case AndroidKeyEvent::KEYCODE_VOLUME_DOWN:
         HandleSpecialKey(ae);
         return;
     }
 
+    nsEventStatus status;
     nsKeyEvent event(PR_TRUE, msg, this);
     InitKeyEvent(event, *ae);
-    DispatchEvent(&event);
+    DispatchEvent(&event, status);
+
+    if (!firePress)
+        return;
 
-    if (isDown) {
-        nsKeyEvent pressEvent(PR_TRUE, NS_KEY_PRESS, this);
-        InitKeyEvent(pressEvent, *ae);
+    nsKeyEvent pressEvent(PR_TRUE, NS_KEY_PRESS, this);
+    InitKeyEvent(pressEvent, *ae);
+    if (status == nsEventStatus_eConsumeNoDefault) {
+        pressEvent.flags |= NS_EVENT_FLAG_NO_DEFAULT;
+    }
 #ifdef ANDROID_DEBUG_WIDGET
-        ALOG("Dispatching key event with keyCode %d charCode %d shift %d alt %d sym/ctrl %d metamask %d", event.keyCode, event.charCode, event.isShift, event.isAlt, event.isControl, ae->MetaState());
+    __android_log_print(ANDROID_LOG_INFO, "Gecko", "Dispatching key pressEvent with keyCode %d charCode %d shift %d alt %d sym/ctrl %d metamask %d", pressEvent.keyCode, pressEvent.charCode, pressEvent.isShift, pressEvent.isAlt, pressEvent.isControl, ae->MetaState());
 #endif
-        DispatchEvent(&pressEvent);
-    }
+    DispatchEvent(&pressEvent);
 }
 
 #ifdef ANDROID_DEBUG_IME
 #define ALOGIME(args...) ALOG(args)
 #else
 #define ALOGIME(args...)
 #endif