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 id17672
push userazakai@mozilla.com
push dateTue, 21 Dec 2010 22:47:09 +0000
treeherdermozilla-central@a2a3a6e8b0e0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki, blocking-fennec
bugs619519
milestone2.0b9pre
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 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