Bug 742036 - Part 3: Pass Android's native keycodes to Flash plugin using nsGUIEvent::pluginEvent. r=masayuki,blassey a=blocking-fennec
authorChris Peterson <cpeterson@mozilla.com>
Thu, 19 Apr 2012 10:49:31 -0700
changeset 95329 d99013587d5bf4b67bb2225c4eee83016e93d5ff
parent 95328 cb4a3672b962fb6460aa37534f89e893b38cf093
child 95330 eec7626671fae19008b98f635c59f98633357d99
push idunknown
push userunknown
push dateunknown
reviewersmasayuki, blassey, blocking-fennec
bugs742036
milestone14.0a1
Bug 742036 - Part 3: Pass Android's native keycodes to Flash plugin using nsGUIEvent::pluginEvent. r=masayuki,blassey a=blocking-fennec
dom/plugins/base/android/Makefile.in
dom/plugins/base/nsPluginInstanceOwner.cpp
widget/android/nsWindow.cpp
widget/android/nsWindow.h
--- a/dom/plugins/base/android/Makefile.in
+++ b/dom/plugins/base/android/Makefile.in
@@ -48,16 +48,17 @@ LIBRARY_NAME	= gkpluginandroid_s
 LIBXUL_LIBRARY   = 1
 FORCE_STATIC_LIB = 1
 EXPORT_LIBRARY = 1
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 
 EXPORTS = \
+  ANPKeyCodes.h \
   android_npapi.h \
   $(NULL)
 
 CPPSRCS += ANPAudio.cpp    \
            ANPEvent.cpp    \
            ANPMatrix.cpp   \
            ANPSystem.cpp   \
            ANPWindow.cpp   \
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -120,17 +120,16 @@ static NS_DEFINE_CID(kAppShellCID, NS_AP
 #include <gdk/gdk.h>
 #include <gdk/gdkx.h>
 #include <gtk/gtk.h>
 #include "gfxXlibNativeRenderer.h"
 #endif
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "ANPBase.h"
-#include "android_npapi.h"
 #include "AndroidBridge.h"
 #include "AndroidMediaLayer.h"
 using namespace mozilla::dom;
 
 #include <android/log.h>
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
 #endif
 
@@ -2712,43 +2711,23 @@ nsEventStatus nsPluginInstanceOwner::Pro
           }
       }
       break;
 
     case NS_KEY_EVENT:
      {
        const nsKeyEvent& keyEvent = static_cast<const nsKeyEvent&>(anEvent);
        LOG("Firing NS_KEY_EVENT %d %d\n", keyEvent.keyCode, keyEvent.charCode);
-       
-       int modifiers = 0;
-       if (keyEvent.isShift)
-         modifiers |= kShift_ANPKeyModifier;
-       if (keyEvent.isAlt)
-         modifiers |= kAlt_ANPKeyModifier;
-
-       ANPEvent event;
-       event.inSize = sizeof(ANPEvent);
-       event.eventType = kKey_ANPEventType;
-       event.data.key.nativeCode = keyEvent.keyCode;
-       event.data.key.virtualCode = keyEvent.charCode;
-       event.data.key.modifiers = modifiers;
-       event.data.key.repeatCount = 0;
-       event.data.key.unichar = 0;
-       switch (anEvent.message)
-         {
-         case NS_KEY_DOWN:
-           event.data.key.action = kDown_ANPKeyAction;
-           mInstance->HandleEvent(&event, nsnull);
-           break;
-           
-         case NS_KEY_UP:
-           event.data.key.action = kUp_ANPKeyAction;
-           mInstance->HandleEvent(&event, nsnull);
-           break;
-         }
+       // pluginEvent is initialized by nsWindow::InitKeyEvent().
+       ANPEvent* pluginEvent = reinterpret_cast<ANPEvent*>(keyEvent.pluginEvent);
+       if (pluginEvent) {
+         MOZ_ASSERT(pluginEvent->inSize == sizeof(ANPEvent));
+         MOZ_ASSERT(pluginEvent->eventType == kKey_ANPEventType);
+         mInstance->HandleEvent(pluginEvent, nsnull);
+       }
      }
     }
     rv = nsEventStatus_eConsumeNoDefault;
 #endif
  
   return rv;
 }
 
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -72,16 +72,17 @@ using mozilla::unused;
 #include "BasicLayers.h"
 #include "LayerManagerOGL.h"
 #include "GLContext.h"
 #include "GLContextProvider.h"
 
 #include "nsTArray.h"
 
 #include "AndroidBridge.h"
+#include "android_npapi.h"
 
 #include "imgIEncoder.h"
 
 #include "nsStringGlue.h"
 #include "nsAutoPtr.h"
 
 using namespace mozilla;
 using namespace mozilla::widget;
@@ -1731,31 +1732,73 @@ static unsigned int ConvertAndroidKeyCod
 
         default:
             ALOG("ConvertAndroidKeyCodeToDOMKeyCode: "
                  "No DOM keycode for Android keycode %d", androidKeyCode);
         return 0;
     }
 }
 
+static void InitPluginEvent(ANPEvent* pluginEvent, ANPKeyActions keyAction,
+                            AndroidGeckoEvent& key)
+{
+    int androidKeyCode = key.KeyCode();
+    PRUint32 domKeyCode = ConvertAndroidKeyCodeToDOMKeyCode(androidKeyCode);
+
+    int modifiers = 0;
+    if (key.IsAltPressed())
+      modifiers |= kAlt_ANPKeyModifier;
+    if (key.IsShiftPressed())
+      modifiers |= kShift_ANPKeyModifier;
+
+    pluginEvent->inSize = sizeof(ANPEvent);
+    pluginEvent->eventType = kKey_ANPEventType;
+    pluginEvent->data.key.action = keyAction;
+    pluginEvent->data.key.nativeCode = androidKeyCode;
+    pluginEvent->data.key.virtualCode = domKeyCode;
+    pluginEvent->data.key.unichar = key.UnicodeChar();
+    pluginEvent->data.key.modifiers = modifiers;
+    pluginEvent->data.key.repeatCount = key.RepeatCount();
+}
+
 void
-nsWindow::InitKeyEvent(nsKeyEvent& event, AndroidGeckoEvent& key)
+nsWindow::InitKeyEvent(nsKeyEvent& event, AndroidGeckoEvent& key,
+                       ANPEvent* pluginEvent)
 {
-    event.keyCode = ConvertAndroidKeyCodeToDOMKeyCode(key.KeyCode());
+    int androidKeyCode = key.KeyCode();
+    PRUint32 domKeyCode = ConvertAndroidKeyCodeToDOMKeyCode(androidKeyCode);
 
-    // 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;
+    if (event.message == NS_KEY_PRESS) {
+        // Android gives us \n, so filter out some control characters.
+        event.isChar = (key.UnicodeChar() >= ' ');
+        event.charCode = event.isChar ? key.UnicodeChar() : 0;
+        event.keyCode = (event.charCode > 0) ? 0 : domKeyCode;
+        event.pluginEvent = NULL;
+    } else {
+#ifdef DEBUG
+        if (event.message != NS_KEY_DOWN && event.message != NS_KEY_UP) {
+            ALOG("InitKeyEvent: unexpected event.message %d", event.message);
+        }
+#endif // DEBUG
+
+        // Flash will want a pluginEvent for keydown and keyup events.
+        ANPKeyActions action = event.message == NS_KEY_DOWN
+                             ? kDown_ANPKeyAction
+                             : kUp_ANPKeyAction;
+        InitPluginEvent(pluginEvent, action, key);
+
+        event.isChar = false;
+        event.charCode = 0;
+        event.keyCode = domKeyCode;
+        event.pluginEvent = pluginEvent;
     }
-    event.isShift = !!(key.MetaState() & AndroidKeyEvent::META_SHIFT_ON);
+
+    event.isShift = key.IsShiftPressed();
     event.isControl = gMenu;
-    event.isAlt = !!(key.MetaState() & AndroidKeyEvent::META_ALT_ON);
+    event.isAlt = key.IsAltPressed();
     event.isMeta = false;
     event.time = key.Time();
 
     if (gMenu)
         gMenuConsumed = true;
 }
 
 void
@@ -1788,17 +1831,18 @@ nsWindow::HandleSpecialKey(AndroidGeckoE
                 gMenu = true;
                 gMenuConsumed = isLongPress;
                 break;
         }
     } else {
         switch (keyCode) {
             case AndroidKeyEvent::KEYCODE_BACK: {
                 nsKeyEvent pressEvent(true, NS_KEY_PRESS, this);
-                InitKeyEvent(pressEvent, *ae);
+                ANPEvent pluginEvent;
+                InitKeyEvent(pressEvent, *ae, &pluginEvent);
                 DispatchEvent(&pressEvent);
                 return;
             }
             case AndroidKeyEvent::KEYCODE_MENU:
                 gMenu = false;
                 if (!gMenuConsumed) {
                     command = nsGkAtoms::Menu;
                     doCommand = true;
@@ -1858,26 +1902,27 @@ nsWindow::OnKeyEvent(AndroidGeckoEvent *
     case AndroidKeyEvent::KEYCODE_VOLUME_UP:
     case AndroidKeyEvent::KEYCODE_VOLUME_DOWN:
         HandleSpecialKey(ae);
         return;
     }
 
     nsEventStatus status;
     nsKeyEvent event(true, msg, this);
-    InitKeyEvent(event, *ae);
+    ANPEvent pluginEvent;
+    InitKeyEvent(event, *ae, &pluginEvent);
     DispatchEvent(&event, status);
 
     if (Destroyed())
         return;
     if (!firePress)
         return;
 
     nsKeyEvent pressEvent(true, NS_KEY_PRESS, this);
-    InitKeyEvent(pressEvent, *ae);
+    InitKeyEvent(pressEvent, *ae, &pluginEvent);
     if (status == nsEventStatus_eConsumeNoDefault) {
         pressEvent.flags |= NS_EVENT_FLAG_NO_DEFAULT;
     }
 #ifdef DEBUG_ANDROID_WIDGET
     __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);
 }
@@ -1992,20 +2037,21 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *
                 AndroidBridge::Bridge()->ReturnIMEQueryResult(
                     event.mReply.mString.get(), 
                     event.mReply.mString.Length(), 0, 0);
             }
             //ALOGIME("IME:     -> l=%u", event.mReply.mString.Length());
         }
         return;
     case AndroidGeckoEvent::IME_DELETE_TEXT:
-        {   
+        {
             ALOGIME("IME: IME_DELETE_TEXT");
             nsKeyEvent event(true, NS_KEY_PRESS, this);
-            InitEvent(event, nsnull);
+            ANPEvent pluginEvent;
+            InitKeyEvent(event, *ae, &pluginEvent);
             event.keyCode = NS_VK_BACK;
             DispatchEvent(&event);
         }
         return;
     case AndroidGeckoEvent::IME_SET_SELECTION:
         {
             ALOGIME("IME: IME_SET_SELECTION: o=%u, l=%d", ae->Offset(), ae->Count());
 
--- a/widget/android/nsWindow.h
+++ b/widget/android/nsWindow.h
@@ -46,16 +46,18 @@
 #ifdef MOZ_JAVA_COMPOSITOR
 #include "AndroidJavaWrappers.h"
 #include "Layers.h"
 #endif
 
 class gfxASurface;
 class nsIdleService;
 
+struct ANPEvent;
+
 namespace mozilla {
     class AndroidGeckoEvent;
     class AndroidKeyEvent;
 
     namespace layers {
         class CompositorParent;
         class CompositorChild;
     }
@@ -226,17 +228,18 @@ protected:
 
     InputContext mInputContext;
 
     static void DumpWindows();
     static void DumpWindows(const nsTArray<nsWindow*>& wins, int indent = 0);
     static void LogWindow(nsWindow *win, int index, int indent);
 
 private:
-    void InitKeyEvent(nsKeyEvent& event, mozilla::AndroidGeckoEvent& key);
+    void InitKeyEvent(nsKeyEvent& event, mozilla::AndroidGeckoEvent& key,
+                      ANPEvent* pluginEvent);
     bool DispatchMultitouchEvent(nsTouchEvent &event,
                              mozilla::AndroidGeckoEvent *ae);
     void DispatchMotionEvent(nsInputEvent &event,
                              mozilla::AndroidGeckoEvent *ae,
                              const nsIntPoint &refPoint);
     void DispatchGestureEvent(PRUint32 msg, PRUint32 direction, double delta,
                               const nsIntPoint &refPoint, PRUint64 time);
     void HandleSpecialKey(mozilla::AndroidGeckoEvent *ae);