Bug 719647 - Add Touch Event support to Gonk widget backend, r=cjones
authorMichael Wu <mwu@mozilla.com>
Wed, 25 Jan 2012 12:37:31 -0800
changeset 87008 5fc3efb1d791bb8a3787c3ca4d48b789aa933b52
parent 87007 c3d1e9d47da338983a6a4dd40b5294ad6f74ccdd
child 87009 94bae0abad47cca863d5fdae87a217a3b3b29ba1
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs719647
milestone12.0a1
Bug 719647 - Add Touch Event support to Gonk widget backend, r=cjones
configure.in
widget/gonk/Makefile.in
widget/gonk/nsAppShell.cpp
--- a/configure.in
+++ b/configure.in
@@ -4901,22 +4901,24 @@ cairo-android)
     if test "$MOZ_BUILD_APP" = "mobile/xul"; then
         MOZ_OLD_LINKER=1
     fi
     MOZ_TOUCH=1
     ;;
 
 cairo-gonk)
     AC_DEFINE(MOZ_WIDGET_GONK)
+    AC_DEFINE(MOZ_TOUCH)
     MOZ_WIDGET_TOOLKIT=gonk
     TK_CFLAGS='$(MOZ_CAIRO_CFLAGS)'
     TK_LIBS='$(MOZ_CAIRO_LIBS)'
     MOZ_WEBGL=1
     MOZ_PDF_PRINTING=1
     MOZ_B2G_RIL=1
+    MOZ_TOUCH=1
     ;;
 
 esac
 
 AC_SUBST(MOZ_OLD_LINKER)
 AC_SUBST(MOZ_PDF_PRINTING)
 if test "$MOZ_PDF_PRINTING"; then
    PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
--- a/widget/gonk/Makefile.in
+++ b/widget/gonk/Makefile.in
@@ -66,12 +66,13 @@ SHARED_LIBRARY_LIBS = ../xpwidgets/libxp
 include $(topsrcdir)/config/rules.mk
 
 DEFINES += -D_IMPL_NS_WIDGET
 
 LOCAL_INCLUDES += \
 	-I$(topsrcdir)/widget/xpwidgets \
 	-I$(topsrcdir)/widget/shared \
 	-I$(topsrcdir)/dom/system/android \
+	-I$(topsrcdir)/content/events/src \
 	-I$(srcdir) \
 	$(NULL)
 
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
--- a/widget/gonk/nsAppShell.cpp
+++ b/widget/gonk/nsAppShell.cpp
@@ -50,16 +50,17 @@
 #include <sys/types.h>
 #include <unistd.h>
 
 #include "nscore.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/Services.h"
 #include "nsAppShell.h"
+#include "nsDOMTouchEvent.h"
 #include "nsGkAtoms.h"
 #include "nsGUIEvent.h"
 #include "nsIObserverService.h"
 #include "nsWindow.h"
 
 #include "android/log.h"
 #include "ui/EventHub.h"
 #include "ui/InputReader.h"
@@ -102,16 +103,42 @@ pipeHandler(int fd, FdHandler *data)
 {
     ssize_t len;
     do {
         char tmp[32];
         len = read(fd, tmp, sizeof(tmp));
     } while (len > 0);
 }
 
+struct Touch {
+    int32_t id;
+    PointerCoords coords;
+};
+
+struct UserInputData {
+    uint64_t timeMs;
+    enum {
+        MOTION_DATA,
+        KEY_DATA
+    } type;
+    int32_t action;
+    int32_t flags;
+    int32_t metaState;
+    union {
+        struct {
+            int32_t keyCode;
+            int32_t scanCode;
+        } key;
+        struct {
+            int32_t touchCount;
+            Touch touches[MAX_POINTERS];
+        } motion;
+    };
+};
+
 static void
 sendMouseEvent(PRUint32 msg, uint64_t timeMs, int x, int y)
 {
     nsMouseEvent event(true, msg, NULL,
                        nsMouseEvent::eReal, nsMouseEvent::eNormal);
 
     event.refPoint.x = x;
     event.refPoint.y = y;
@@ -122,16 +149,72 @@ sendMouseEvent(PRUint32 msg, uint64_t ti
     event.isAlt = false;
     event.button = nsMouseEvent::eLeftButton;
     if (msg != NS_MOUSE_MOVE)
         event.clickCount = 1;
 
     nsWindow::DispatchInputEvent(event);
 }
 
+static void
+addDOMTouch(UserInputData& data, nsTouchEvent& event, int i)
+{
+    const Touch& touch = data.motion.touches[i];
+    event.touches.AppendElement(
+        new nsDOMTouch(touch.id,
+                       nsIntPoint(touch.coords.x, touch.coords.y),
+                       nsIntPoint(touch.coords.size, touch.coords.size),
+                       0,
+                       touch.coords.pressure));
+}
+
+static nsEventStatus
+sendTouchEvent(UserInputData& data)
+{
+    PRUint32 msg;
+    int32_t action = data.action & AMOTION_EVENT_ACTION_MASK;
+    switch (action) {
+    case AMOTION_EVENT_ACTION_DOWN:
+    case AMOTION_EVENT_ACTION_POINTER_DOWN:
+        msg = NS_TOUCH_START;
+        break;
+    case AMOTION_EVENT_ACTION_MOVE:
+        msg = NS_TOUCH_MOVE;
+        break;
+    case AMOTION_EVENT_ACTION_UP:
+    case AMOTION_EVENT_ACTION_POINTER_UP:
+        msg = NS_TOUCH_END;
+        break;
+    case AMOTION_EVENT_ACTION_OUTSIDE:
+    case AMOTION_EVENT_ACTION_CANCEL:
+        msg = NS_TOUCH_CANCEL;
+        break;
+    }
+
+    nsTouchEvent event(true, msg, NULL);
+
+    event.time = data.timeMs;
+    event.isShift = false;
+    event.isControl = false;
+    event.isMeta = false;
+    event.isAlt = false;
+
+    int32_t i;
+    if (msg == NS_TOUCH_END) {
+        i = data.action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK;
+        i >>= AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
+        addDOMTouch(data, event, i);
+    } else {
+        for (i = 0; i < data.motion.touchCount; ++i)
+            addDOMTouch(data, event, i);
+    }
+
+    return nsWindow::DispatchInputEvent(event);
+}
+
 static nsEventStatus
 sendKeyEventWithMsg(PRUint32 keyCode,
                     PRUint32 msg,
                     uint64_t timeMs,
                     PRUint32 flags)
 {
     nsKeyEvent event(true, msg, NULL);
     event.keyCode = keyCode;
@@ -190,36 +273,16 @@ maybeSendKeyEvent(int keyCode, bool pres
             sendSpecialKeyEvent(nsGkAtoms::VolumeDown, timeMs);
         break;
     default:
         VERBOSE_LOG("Got unknown key event code. type 0x%04x code 0x%04x value %d",
                     keyCode, pressed);
     }
 }
 
-struct UserInputData {
-    uint64_t timeMs;
-    enum {
-        MOTION_DATA,
-        KEY_DATA
-    } type;
-    int32_t action;
-    int32_t flags;
-    int32_t metaState;
-    union {
-        struct {
-            int32_t keyCode;
-            int32_t scanCode;
-        } key;
-        struct {
-            PointerCoords coords;
-        } motion;
-    };
-};
-
 class GeckoInputReaderPolicy : public InputReaderPolicyInterface {
 public:
     GeckoInputReaderPolicy() {}
 
     virtual bool getDisplayInfo(int32_t displayId,
             int32_t* width, int32_t* height, int32_t* orientation);
     virtual bool filterTouchEvents();
     virtual bool filterJumpyTouchEvents();
@@ -407,41 +470,48 @@ GeckoInputDispatcher::dump(String8& dump
 void
 GeckoInputDispatcher::dispatchOnce()
 {
     UserInputData data;
     {
         MutexAutoLock lock(mQueueLock);
         if (mEventQueue.empty())
             return;
-
         data = mEventQueue.front();
         mEventQueue.pop();
         if (!mEventQueue.empty())
             gAppShell->NotifyNativeEvent();
     }
 
     switch (data.type) {
     case UserInputData::MOTION_DATA: {
+        nsEventStatus status = sendTouchEvent(data);
+        if (status == nsEventStatus_eConsumeNoDefault)
+            break;
+
         PRUint32 msg;
-        switch (data.action) {
+        switch (data.action & AMOTION_EVENT_ACTION_MASK) {
         case AMOTION_EVENT_ACTION_DOWN:
             msg = NS_MOUSE_BUTTON_DOWN;
             break;
+        case AMOTION_EVENT_ACTION_POINTER_DOWN:
+        case AMOTION_EVENT_ACTION_POINTER_UP:
         case AMOTION_EVENT_ACTION_MOVE:
             msg = NS_MOUSE_MOVE;
             break;
+        case AMOTION_EVENT_ACTION_OUTSIDE:
+        case AMOTION_EVENT_ACTION_CANCEL:
         case AMOTION_EVENT_ACTION_UP:
             msg = NS_MOUSE_BUTTON_UP;
             break;
         }
         sendMouseEvent(msg,
                        data.timeMs,
-                       data.motion.coords.x,
-                       data.motion.coords.y);
+                       data.motion.touches[0].coords.x,
+                       data.motion.touches[0].coords.y);
         break;
     }
     case UserInputData::KEY_DATA:
         maybeSendKeyEvent(data.key.scanCode,
                           data.action == AKEY_EVENT_ACTION_DOWN,
                           data.timeMs);
         break;
     }
@@ -503,17 +573,23 @@ GeckoInputDispatcher::notifyMotion(nsecs
                                    nsecs_t downTime)
 {
     UserInputData data;
     data.timeMs = nanosecsToMillisecs(eventTime);
     data.type = UserInputData::MOTION_DATA;
     data.action = action;
     data.flags = flags;
     data.metaState = metaState;
-    data.motion.coords = *pointerCoords;
+    MOZ_ASSERT(pointerCount <= MAX_POINTERS);
+    data.motion.touchCount = pointerCount;
+    for (int32_t i = 0; i < pointerCount; ++i) {
+        Touch& touch = data.motion.touches[i];
+        touch.id = pointerIds[i];
+        memcpy(&touch.coords, &pointerCoords[i], sizeof(*pointerCoords));
+    }
     {
         MutexAutoLock lock(mQueueLock);
         mEventQueue.push(data);
     }
     gAppShell->NotifyNativeEvent();
 }
 
 void