From 8d03b81c6137e932a8ffa835974a10b8d57a21ff Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Wed, 25 Jan 2012 12:37:31 -0800 Subject: [PATCH] Bug 719647 - Add Touch Event support to Gonk widget backend, r=cjones --- configure.in | 2 + widget/gonk/Makefile.in | 1 + widget/gonk/nsAppShell.cpp | 126 +++++++++++++++++++++++++++++-------- 3 files changed, 104 insertions(+), 25 deletions(-) diff --git a/configure.in b/configure.in index 611316308f9..29864c5845a 100644 --- a/configure.in +++ b/configure.in @@ -4906,12 +4906,14 @@ cairo-android) 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 diff --git a/widget/gonk/Makefile.in b/widget/gonk/Makefile.in index 32e8505b4a7..65676ee862d 100644 --- a/widget/gonk/Makefile.in +++ b/widget/gonk/Makefile.in @@ -71,6 +71,7 @@ LOCAL_INCLUDES += \ -I$(topsrcdir)/widget/xpwidgets \ -I$(topsrcdir)/widget/shared \ -I$(topsrcdir)/dom/system/android \ + -I$(topsrcdir)/content/events/src \ -I$(srcdir) \ $(NULL) diff --git a/widget/gonk/nsAppShell.cpp b/widget/gonk/nsAppShell.cpp index 05f2f39b18a..2d18ef958ff 100644 --- a/widget/gonk/nsAppShell.cpp +++ b/widget/gonk/nsAppShell.cpp @@ -55,6 +55,7 @@ #include "mozilla/Mutex.h" #include "mozilla/Services.h" #include "nsAppShell.h" +#include "nsDOMTouchEvent.h" #include "nsGkAtoms.h" #include "nsGUIEvent.h" #include "nsIObserverService.h" @@ -107,6 +108,32 @@ pipeHandler(int fd, FdHandler *data) } 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) { @@ -127,6 +154,62 @@ sendMouseEvent(PRUint32 msg, uint64_t timeMs, int x, int y) 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, @@ -195,26 +278,6 @@ maybeSendKeyEvent(int keyCode, bool pressed, uint64_t timeMs) } } -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() {} @@ -412,7 +475,6 @@ GeckoInputDispatcher::dispatchOnce() MutexAutoLock lock(mQueueLock); if (mEventQueue.empty()) return; - data = mEventQueue.front(); mEventQueue.pop(); if (!mEventQueue.empty()) @@ -421,22 +483,30 @@ GeckoInputDispatcher::dispatchOnce() 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: @@ -508,7 +578,13 @@ GeckoInputDispatcher::notifyMotion(nsecs_t eventTime, 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);