mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 603008 - Platform support for multitouch events. r=smaug
* * * Bug 603008 - Platform support for multitouch events. * * * ifdefandroid
This commit is contained in:
parent
cde21ae60f
commit
43680b21b4
@ -148,6 +148,7 @@ MOZ_SPELLCHECK = @MOZ_SPELLCHECK@
|
||||
MOZ_ANDROID_HISTORY = @MOZ_ANDROID_HISTORY@
|
||||
MOZ_WEBSMS_BACKEND = @MOZ_WEBSMS_BACKEND@
|
||||
MOZ_JAVA_COMPOSITOR = @MOZ_JAVA_COMPOSITOR@
|
||||
MOZ_TOUCH = @MOZ_TOUCH@
|
||||
MOZ_PROFILELOCKING = @MOZ_PROFILELOCKING@
|
||||
MOZ_FEEDS = @MOZ_FEEDS@
|
||||
MOZ_TOOLKIT_SEARCH = @MOZ_TOOLKIT_SEARCH@
|
||||
|
@ -4902,6 +4902,7 @@ cairo-uikit)
|
||||
|
||||
cairo-android)
|
||||
AC_DEFINE(MOZ_WIDGET_ANDROID)
|
||||
AC_DEFINE(MOZ_TOUCH)
|
||||
MOZ_WIDGET_TOOLKIT=android
|
||||
TK_CFLAGS='$(MOZ_CAIRO_CFLAGS)'
|
||||
TK_LIBS='$(MOZ_CAIRO_LIBS)'
|
||||
@ -4909,6 +4910,7 @@ cairo-android)
|
||||
MOZ_PDF_PRINTING=1
|
||||
MOZ_INSTRUMENT_EVENT_LOOP=1
|
||||
MOZ_OLD_LINKER=1
|
||||
MOZ_TOUCH=1
|
||||
;;
|
||||
|
||||
cairo-gonk)
|
||||
|
@ -449,29 +449,29 @@ WINDOW_ONLY_EVENT(deviceorientation,
|
||||
NS_EVENT)
|
||||
|
||||
TOUCH_EVENT(touchstart,
|
||||
NS_USER_DEFINED_EVENT,
|
||||
NS_TOUCH_START,
|
||||
EventNameType_All,
|
||||
NS_INPUT_EVENT)
|
||||
NS_TOUCH_EVENT)
|
||||
TOUCH_EVENT(touchend,
|
||||
NS_USER_DEFINED_EVENT,
|
||||
NS_TOUCH_END,
|
||||
EventNameType_All,
|
||||
NS_INPUT_EVENT)
|
||||
NS_TOUCH_EVENT)
|
||||
TOUCH_EVENT(touchmove,
|
||||
NS_USER_DEFINED_EVENT,
|
||||
NS_TOUCH_MOVE,
|
||||
EventNameType_All,
|
||||
NS_INPUT_EVENT )
|
||||
NS_TOUCH_EVENT )
|
||||
TOUCH_EVENT(touchenter,
|
||||
NS_USER_DEFINED_EVENT,
|
||||
NS_TOUCH_ENTER,
|
||||
EventNameType_All,
|
||||
NS_INPUT_EVENT )
|
||||
NS_TOUCH_EVENT )
|
||||
TOUCH_EVENT(touchleave,
|
||||
NS_USER_DEFINED_EVENT,
|
||||
NS_TOUCH_LEAVE,
|
||||
EventNameType_All,
|
||||
NS_INPUT_EVENT)
|
||||
NS_TOUCH_EVENT)
|
||||
TOUCH_EVENT(touchcancel,
|
||||
NS_USER_DEFINED_EVENT,
|
||||
NS_TOUCH_CANCEL,
|
||||
EventNameType_All,
|
||||
NS_INPUT_EVENT)
|
||||
NS_TOUCH_EVENT)
|
||||
|
||||
DOCUMENT_ONLY_EVENT(readystatechange,
|
||||
NS_READYSTATECHANGE,
|
||||
|
@ -141,7 +141,7 @@ NS_NewDOMCloseEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContex
|
||||
nsresult
|
||||
NS_NewDOMMozTouchEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsMozTouchEvent* aEvent);
|
||||
nsresult
|
||||
NS_NewDOMTouchEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsInputEvent *aEvent);
|
||||
NS_NewDOMTouchEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsTouchEvent *aEvent);
|
||||
nsresult
|
||||
NS_NewDOMCustomEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent* aEvent);
|
||||
nsresult
|
||||
|
@ -63,6 +63,8 @@
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "DictionaryHelpers.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
@ -110,6 +112,12 @@ static const char* const sEventNames[] = {
|
||||
"MozTouchDown",
|
||||
"MozTouchMove",
|
||||
"MozTouchUp",
|
||||
"touchstart",
|
||||
"touchend",
|
||||
"touchmove",
|
||||
"touchcancel",
|
||||
"touchenter",
|
||||
"touchleave",
|
||||
"MozScrolledAreaChanged",
|
||||
"transitionend",
|
||||
"animationstart",
|
||||
@ -902,6 +910,13 @@ NS_METHOD nsDOMEvent::DuplicatePrivateData()
|
||||
isInputEvent = true;
|
||||
break;
|
||||
}
|
||||
case NS_TOUCH_EVENT:
|
||||
{
|
||||
newEvent = new nsTouchEvent(false, msg, nsnull);
|
||||
NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
|
||||
isInputEvent = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
NS_WARNING("Unknown event type!!!");
|
||||
@ -1165,6 +1180,92 @@ nsDOMEvent::Shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
nsIntPoint
|
||||
nsDOMEvent::GetScreenCoords(nsPresContext* aPresContext,
|
||||
nsEvent* aEvent,
|
||||
nsIntPoint aPoint)
|
||||
{
|
||||
if (!aEvent ||
|
||||
(aEvent->eventStructType != NS_MOUSE_EVENT &&
|
||||
aEvent->eventStructType != NS_POPUP_EVENT &&
|
||||
aEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
|
||||
aEvent->eventStructType != NS_MOZTOUCH_EVENT &&
|
||||
aEvent->eventStructType != NS_TOUCH_EVENT &&
|
||||
aEvent->eventStructType != NS_DRAG_EVENT &&
|
||||
aEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT)) {
|
||||
return nsIntPoint(0, 0);
|
||||
}
|
||||
|
||||
nsGUIEvent* guiEvent = static_cast<nsGUIEvent*>(aEvent);
|
||||
if (!guiEvent->widget) {
|
||||
return aPoint;
|
||||
}
|
||||
|
||||
nsIntPoint offset = aPoint + guiEvent->widget->WidgetToScreenOffset();
|
||||
nscoord factor = aPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel();
|
||||
return nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(offset.x * factor),
|
||||
nsPresContext::AppUnitsToIntCSSPixels(offset.y * factor));
|
||||
}
|
||||
|
||||
//static
|
||||
nsIntPoint
|
||||
nsDOMEvent::GetPageCoords(nsPresContext* aPresContext,
|
||||
nsEvent* aEvent,
|
||||
nsIntPoint aPoint,
|
||||
nsIntPoint aDefaultPoint)
|
||||
{
|
||||
nsIntPoint pagePoint = nsDOMEvent::GetClientCoords(aPresContext,
|
||||
aEvent,
|
||||
aPoint,
|
||||
aDefaultPoint);
|
||||
|
||||
// If there is some scrolling, add scroll info to client point.
|
||||
if (aPresContext && aPresContext->GetPresShell()) {
|
||||
nsIPresShell* shell = aPresContext->GetPresShell();
|
||||
nsIScrollableFrame* scrollframe = shell->GetRootScrollFrameAsScrollable();
|
||||
if (scrollframe) {
|
||||
nsPoint pt = scrollframe->GetScrollPosition();
|
||||
pagePoint += nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(pt.x),
|
||||
nsPresContext::AppUnitsToIntCSSPixels(pt.y));
|
||||
}
|
||||
}
|
||||
|
||||
return pagePoint;
|
||||
}
|
||||
|
||||
// static
|
||||
nsIntPoint
|
||||
nsDOMEvent::GetClientCoords(nsPresContext* aPresContext,
|
||||
nsEvent* aEvent,
|
||||
nsIntPoint aPoint,
|
||||
nsIntPoint aDefaultPoint)
|
||||
{
|
||||
if (!aEvent ||
|
||||
(aEvent->eventStructType != NS_MOUSE_EVENT &&
|
||||
aEvent->eventStructType != NS_POPUP_EVENT &&
|
||||
aEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
|
||||
aEvent->eventStructType != NS_MOZTOUCH_EVENT &&
|
||||
aEvent->eventStructType != NS_TOUCH_EVENT &&
|
||||
aEvent->eventStructType != NS_DRAG_EVENT &&
|
||||
aEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT) ||
|
||||
!aPresContext ||
|
||||
!((nsGUIEvent*)aEvent)->widget) {
|
||||
return aDefaultPoint;
|
||||
}
|
||||
|
||||
nsPoint pt(0, 0);
|
||||
nsIPresShell* shell = aPresContext->GetPresShell();
|
||||
if (!shell) {
|
||||
return nsIntPoint(0, 0);
|
||||
}
|
||||
nsIFrame* rootFrame = shell->GetRootFrame();
|
||||
if (rootFrame)
|
||||
pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, aPoint, rootFrame);
|
||||
|
||||
return nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(pt.x),
|
||||
nsPresContext::AppUnitsToIntCSSPixels(pt.y));
|
||||
}
|
||||
|
||||
// To be called ONLY by nsDOMEvent::GetType (which has the additional
|
||||
// logic for handling user-defined events).
|
||||
// static
|
||||
@ -1347,6 +1448,18 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
|
||||
return sEventNames[eDOMEvents_SVGScroll];
|
||||
case NS_SVG_ZOOM:
|
||||
return sEventNames[eDOMEvents_SVGZoom];
|
||||
case NS_TOUCH_START:
|
||||
return sEventNames[eDOMEvents_touchstart];
|
||||
case NS_TOUCH_MOVE:
|
||||
return sEventNames[eDOMEvents_touchmove];
|
||||
case NS_TOUCH_END:
|
||||
return sEventNames[eDOMEvents_touchend];
|
||||
case NS_TOUCH_ENTER:
|
||||
return sEventNames[eDOMEvents_touchenter];
|
||||
case NS_TOUCH_LEAVE:
|
||||
return sEventNames[eDOMEvents_touchleave];
|
||||
case NS_TOUCH_CANCEL:
|
||||
return sEventNames[eDOMEvents_touchcancel];
|
||||
case NS_SMIL_BEGIN:
|
||||
return sEventNames[eDOMEvents_beginEvent];
|
||||
case NS_SMIL_END:
|
||||
|
@ -195,6 +195,12 @@ public:
|
||||
eDOMEvents_MozTouchDown,
|
||||
eDOMEvents_MozTouchMove,
|
||||
eDOMEvents_MozTouchUp,
|
||||
eDOMEvents_touchstart,
|
||||
eDOMEvents_touchend,
|
||||
eDOMEvents_touchmove,
|
||||
eDOMEvents_touchcancel,
|
||||
eDOMEvents_touchenter,
|
||||
eDOMEvents_touchleave,
|
||||
eDOMEvents_MozScrolledAreaChanged,
|
||||
eDOMEvents_transitionend,
|
||||
eDOMEvents_animationstart,
|
||||
@ -242,6 +248,17 @@ public:
|
||||
static void Shutdown();
|
||||
|
||||
static const char* GetEventName(PRUint32 aEventType);
|
||||
static nsIntPoint GetClientCoords(nsPresContext* aPresContext,
|
||||
nsEvent* aEvent,
|
||||
nsIntPoint aPoint,
|
||||
nsIntPoint aDefaultPoint);
|
||||
static nsIntPoint GetPageCoords(nsPresContext* aPresContext,
|
||||
nsEvent* aEvent,
|
||||
nsIntPoint aPoint,
|
||||
nsIntPoint aDefaultPoint);
|
||||
static nsIntPoint GetScreenCoords(nsPresContext* aPresContext,
|
||||
nsEvent* aEvent,
|
||||
nsIntPoint aPoint);
|
||||
protected:
|
||||
|
||||
// Internal helper functions
|
||||
|
@ -236,7 +236,13 @@ nsDOMMouseEvent::GetRelatedTarget(nsIDOMEventTarget** aRelatedTarget)
|
||||
NS_METHOD nsDOMMouseEvent::GetScreenX(PRInt32* aScreenX)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aScreenX);
|
||||
#ifdef MOZ_TOUCH
|
||||
*aScreenX = nsDOMEvent::GetScreenCoords(mPresContext,
|
||||
mEvent,
|
||||
mEvent->refPoint).x;
|
||||
#else
|
||||
*aScreenX = GetScreenPoint().x;
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -244,7 +250,13 @@ NS_IMETHODIMP
|
||||
nsDOMMouseEvent::GetScreenY(PRInt32* aScreenY)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aScreenY);
|
||||
#ifdef MOZ_TOUCH
|
||||
*aScreenY = nsDOMEvent::GetScreenCoords(mPresContext,
|
||||
mEvent,
|
||||
mEvent->refPoint).y;
|
||||
#else
|
||||
*aScreenY = GetScreenPoint().y;
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -252,7 +264,14 @@ nsDOMMouseEvent::GetScreenY(PRInt32* aScreenY)
|
||||
NS_METHOD nsDOMMouseEvent::GetClientX(PRInt32* aClientX)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aClientX);
|
||||
#ifdef MOZ_TOUCH
|
||||
*aClientX = nsDOMEvent::GetClientCoords(mPresContext,
|
||||
mEvent,
|
||||
mEvent->refPoint,
|
||||
mClientPoint).x;
|
||||
#else
|
||||
*aClientX = GetClientPoint().x;
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -260,7 +279,14 @@ NS_IMETHODIMP
|
||||
nsDOMMouseEvent::GetClientY(PRInt32* aClientY)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aClientY);
|
||||
#ifdef MOZ_TOUCH
|
||||
*aClientY = nsDOMEvent::GetClientCoords(mPresContext,
|
||||
mEvent,
|
||||
mEvent->refPoint,
|
||||
mClientPoint).y;
|
||||
#else
|
||||
*aClientY = GetClientPoint().y;
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "nsIXPCScriptable.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsPresContext.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
@ -75,56 +76,56 @@ nsDOMTouch::GetTarget(nsIDOMEventTarget** aTarget)
|
||||
NS_IMETHODIMP
|
||||
nsDOMTouch::GetScreenX(PRInt32* aScreenX)
|
||||
{
|
||||
*aScreenX = mScreenX;
|
||||
*aScreenX = mScreenPoint.x;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMTouch::GetScreenY(PRInt32* aScreenY)
|
||||
{
|
||||
*aScreenY = mScreenY;
|
||||
*aScreenY = mScreenPoint.y;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMTouch::GetClientX(PRInt32* aClientX)
|
||||
{
|
||||
*aClientX = mClientX;
|
||||
*aClientX = mClientPoint.x;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMTouch::GetClientY(PRInt32* aClientY)
|
||||
{
|
||||
*aClientY = mClientY;
|
||||
*aClientY = mClientPoint.y;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMTouch::GetPageX(PRInt32* aPageX)
|
||||
{
|
||||
*aPageX = mPageX;
|
||||
*aPageX = mPagePoint.x;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMTouch::GetPageY(PRInt32* aPageY)
|
||||
{
|
||||
*aPageY = mPageY;
|
||||
*aPageY = mPagePoint.y;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMTouch::GetRadiusX(PRInt32* aRadiusX)
|
||||
{
|
||||
*aRadiusX = mRadiusX;
|
||||
*aRadiusX = mRadius.x;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMTouch::GetRadiusY(PRInt32* aRadiusY)
|
||||
{
|
||||
*aRadiusY = mRadiusY;
|
||||
*aRadiusY = mRadius.y;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -142,7 +143,27 @@ nsDOMTouch::GetForce(float* aForce)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
nsDOMTouch::Equals(nsIDOMTouch* aTouch)
|
||||
{
|
||||
float force;
|
||||
float orientation;
|
||||
PRInt32 radiusX, radiusY;
|
||||
aTouch->GetForce(&force);
|
||||
aTouch->GetRotationAngle(&orientation);
|
||||
aTouch->GetRadiusX(&radiusX);
|
||||
aTouch->GetRadiusY(&radiusY);
|
||||
return mRefPoint != aTouch->mRefPoint ||
|
||||
(mForce != force) ||
|
||||
(mRotationAngle != orientation) ||
|
||||
(mRadius.x != radiusX) || (mRadius.y != radiusY);
|
||||
}
|
||||
|
||||
// TouchList
|
||||
nsDOMTouchList::nsDOMTouchList(nsTArray<nsCOMPtr<nsIDOMTouch> > &aTouches)
|
||||
{
|
||||
mPoints.AppendElements(aTouches);
|
||||
}
|
||||
|
||||
DOMCI_DATA(TouchList, nsDOMTouchList)
|
||||
|
||||
@ -155,11 +176,11 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMTouchList)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMTouchList)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mPoints)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_OF_NSCOMPTR(mPoints)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMTouchList)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mPoints)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mPoints)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMTouchList)
|
||||
@ -168,14 +189,14 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMTouchList)
|
||||
NS_IMETHODIMP
|
||||
nsDOMTouchList::GetLength(PRUint32* aLength)
|
||||
{
|
||||
*aLength = mPoints.Count();
|
||||
*aLength = mPoints.Length();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMTouchList::Item(PRUint32 aIndex, nsIDOMTouch** aRetVal)
|
||||
{
|
||||
NS_IF_ADDREF(*aRetVal = mPoints.SafeObjectAt(aIndex));
|
||||
NS_IF_ADDREF(*aRetVal = mPoints.SafeElementAt(aIndex, nsnull));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -183,7 +204,7 @@ NS_IMETHODIMP
|
||||
nsDOMTouchList::IdentifiedTouch(PRInt32 aIdentifier, nsIDOMTouch** aRetVal)
|
||||
{
|
||||
*aRetVal = nsnull;
|
||||
for (PRInt32 i = 0; i < mPoints.Count(); ++i) {
|
||||
for (PRUint32 i = 0; i < mPoints.Length(); ++i) {
|
||||
nsCOMPtr<nsIDOMTouch> point = mPoints[i];
|
||||
PRInt32 identifier;
|
||||
if (point && NS_SUCCEEDED(point->GetIdentifier(&identifier)) &&
|
||||
@ -198,12 +219,18 @@ nsDOMTouchList::IdentifiedTouch(PRInt32 aIdentifier, nsIDOMTouch** aRetVal)
|
||||
// TouchEvent
|
||||
|
||||
nsDOMTouchEvent::nsDOMTouchEvent(nsPresContext* aPresContext,
|
||||
nsInputEvent* aEvent)
|
||||
nsTouchEvent* aEvent)
|
||||
: nsDOMUIEvent(aPresContext, aEvent ? aEvent :
|
||||
new nsInputEvent(false, 0, nsnull))
|
||||
new nsTouchEvent(false, 0, nsnull))
|
||||
{
|
||||
if (aEvent) {
|
||||
mEventIsInternal = false;
|
||||
|
||||
for (PRUint32 i = 0; i < aEvent->touches.Length(); ++i) {
|
||||
nsIDOMTouch *touch = aEvent->touches[i];
|
||||
nsDOMTouch *domtouch = static_cast<nsDOMTouch*>(touch);
|
||||
domtouch->InitializePoints(mPresContext, aEvent);
|
||||
}
|
||||
} else {
|
||||
mEventIsInternal = true;
|
||||
mEvent->time = PR_Now();
|
||||
@ -213,7 +240,7 @@ nsDOMTouchEvent::nsDOMTouchEvent(nsPresContext* aPresContext,
|
||||
nsDOMTouchEvent::~nsDOMTouchEvent()
|
||||
{
|
||||
if (mEventIsInternal && mEvent) {
|
||||
delete static_cast<nsInputEvent*>(mEvent);
|
||||
delete static_cast<nsTouchEvent*>(mEvent);
|
||||
mEvent = nsnull;
|
||||
}
|
||||
}
|
||||
@ -257,7 +284,11 @@ nsDOMTouchEvent::InitTouchEvent(const nsAString& aType,
|
||||
nsIDOMTouchList* aTargetTouches,
|
||||
nsIDOMTouchList* aChangedTouches)
|
||||
{
|
||||
nsresult rv = nsDOMUIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail);
|
||||
nsresult rv = nsDOMUIEvent::InitUIEvent(aType,
|
||||
aCanBubble,
|
||||
aCancelable,
|
||||
aView,
|
||||
aDetail);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
static_cast<nsInputEvent*>(mEvent)->isControl = aCtrlKey;
|
||||
@ -273,22 +304,80 @@ nsDOMTouchEvent::InitTouchEvent(const nsAString& aType,
|
||||
NS_IMETHODIMP
|
||||
nsDOMTouchEvent::GetTouches(nsIDOMTouchList** aTouches)
|
||||
{
|
||||
NS_IF_ADDREF(*aTouches = mTouches);
|
||||
return NS_OK;
|
||||
NS_ENSURE_ARG_POINTER(aTouches);
|
||||
NS_ENSURE_STATE(mEvent);
|
||||
nsRefPtr<nsDOMTouchList> t;
|
||||
|
||||
if (mTouches) {
|
||||
return CallQueryInterface(mTouches, aTouches);
|
||||
}
|
||||
|
||||
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(mEvent);
|
||||
if (mEvent->message == NS_TOUCH_END || mEvent->message == NS_TOUCH_CANCEL) {
|
||||
// for touchend events, remove any changed touches from the touches array
|
||||
nsTArray<nsCOMPtr<nsIDOMTouch> > unchangedTouches;
|
||||
nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
|
||||
for (PRUint32 i = 0; i < touches.Length(); ++i) {
|
||||
if (!touches[i]->mChanged) {
|
||||
unchangedTouches.AppendElement(touches[i]);
|
||||
}
|
||||
}
|
||||
t = new nsDOMTouchList(unchangedTouches);
|
||||
} else {
|
||||
t = new nsDOMTouchList(touchEvent->touches);
|
||||
}
|
||||
mTouches = t;
|
||||
return CallQueryInterface(mTouches, aTouches);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMTouchEvent::GetTargetTouches(nsIDOMTouchList** aTargetTouches)
|
||||
{
|
||||
NS_IF_ADDREF(*aTargetTouches = mTargetTouches);
|
||||
return NS_OK;
|
||||
NS_ENSURE_ARG_POINTER(aTargetTouches);
|
||||
NS_ENSURE_STATE(mEvent);
|
||||
|
||||
if (mTargetTouches) {
|
||||
return CallQueryInterface(mTargetTouches, aTargetTouches);
|
||||
}
|
||||
|
||||
nsTArray<nsCOMPtr<nsIDOMTouch> > targetTouches;
|
||||
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(mEvent);
|
||||
nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
|
||||
for (PRUint32 i = 0; i < touches.Length(); ++i) {
|
||||
// for touchend/cancel events, don't append to the target list if this is a
|
||||
// touch that is ending
|
||||
if ((mEvent->message != NS_TOUCH_END &&
|
||||
mEvent->message != NS_TOUCH_CANCEL) || !touches[i]->mChanged) {
|
||||
nsIDOMEventTarget* targetPtr = touches[i]->GetTarget();
|
||||
if (targetPtr == mEvent->target) {
|
||||
targetTouches.AppendElement(touches[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
mTargetTouches = new nsDOMTouchList(targetTouches);
|
||||
return CallQueryInterface(mTargetTouches, aTargetTouches);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMTouchEvent::GetChangedTouches(nsIDOMTouchList** aChangedTouches)
|
||||
{
|
||||
NS_IF_ADDREF(*aChangedTouches = mChangedTouches);
|
||||
return NS_OK;
|
||||
NS_ENSURE_ARG_POINTER(aChangedTouches);
|
||||
NS_ENSURE_STATE(mEvent);
|
||||
|
||||
if (mChangedTouches) {
|
||||
return CallQueryInterface(mChangedTouches, aChangedTouches);
|
||||
}
|
||||
|
||||
nsTArray<nsCOMPtr<nsIDOMTouch> > changedTouches;
|
||||
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(mEvent);
|
||||
nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
|
||||
for (PRUint32 i = 0; i < touches.Length(); ++i) {
|
||||
if (touches[i]->mChanged) {
|
||||
changedTouches.AppendElement(touches[i]);
|
||||
}
|
||||
}
|
||||
mChangedTouches = new nsDOMTouchList(changedTouches);
|
||||
return CallQueryInterface(mChangedTouches, aChangedTouches);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -337,7 +426,7 @@ nsDOMTouchEvent::PrefEnabled()
|
||||
nsresult
|
||||
NS_NewDOMTouchEvent(nsIDOMEvent** aInstancePtrResult,
|
||||
nsPresContext* aPresContext,
|
||||
nsInputEvent *aEvent)
|
||||
nsTouchEvent *aEvent)
|
||||
{
|
||||
nsDOMTouchEvent* it = new nsDOMTouchEvent(aPresContext, aEvent);
|
||||
|
||||
|
@ -40,7 +40,7 @@
|
||||
#include "nsDOMUIEvent.h"
|
||||
#include "nsIDOMTouchEvent.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsDOMTouch : public nsIDOMTouch
|
||||
{
|
||||
@ -57,33 +57,72 @@ public:
|
||||
PRInt32 aRadiusY,
|
||||
float aRotationAngle,
|
||||
float aForce)
|
||||
: mTarget(aTarget),
|
||||
mIdentifier(aIdentifier),
|
||||
mPageX(aPageX),
|
||||
mPageY(aPageY),
|
||||
mScreenX(aScreenX),
|
||||
mScreenY(aScreenY),
|
||||
mClientX(aClientX),
|
||||
mClientY(aClientY),
|
||||
mRadiusX(aRadiusX),
|
||||
mRadiusY(aRadiusY),
|
||||
mRotationAngle(aRotationAngle),
|
||||
mForce(aForce)
|
||||
{}
|
||||
{
|
||||
mTarget = aTarget;
|
||||
mIdentifier = aIdentifier;
|
||||
mPagePoint = nsIntPoint(aPageX, aPageY);
|
||||
mScreenPoint = nsIntPoint(aScreenX, aScreenY);
|
||||
mClientPoint = nsIntPoint(aClientX, aClientY);
|
||||
mRefPoint = nsIntPoint(0, 0);
|
||||
mPointsInitialized = true;
|
||||
mRadius.x = aRadiusX;
|
||||
mRadius.y = aRadiusY;
|
||||
mRotationAngle = aRotationAngle;
|
||||
mForce = aForce;
|
||||
|
||||
mChanged = false;
|
||||
mMessage = 0;
|
||||
}
|
||||
nsDOMTouch(PRInt32 aIdentifier,
|
||||
nsIntPoint aPoint,
|
||||
nsIntPoint aRadius,
|
||||
float aRotationAngle,
|
||||
float aForce)
|
||||
{
|
||||
mIdentifier = aIdentifier;
|
||||
mPagePoint = nsIntPoint(0, 0);
|
||||
mScreenPoint = nsIntPoint(0, 0);
|
||||
mClientPoint = nsIntPoint(0, 0);
|
||||
mRefPoint = aPoint;
|
||||
mPointsInitialized = false;
|
||||
mRadius = aRadius;
|
||||
mRotationAngle = aRotationAngle;
|
||||
mForce = aForce;
|
||||
|
||||
mChanged = false;
|
||||
mMessage = 0;
|
||||
}
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMTouch)
|
||||
NS_DECL_NSIDOMTOUCH
|
||||
void InitializePoints(nsPresContext* aPresContext, nsEvent* aEvent)
|
||||
{
|
||||
if (mPointsInitialized) {
|
||||
return;
|
||||
}
|
||||
mClientPoint = nsDOMEvent::GetClientCoords(aPresContext,
|
||||
aEvent,
|
||||
mRefPoint,
|
||||
mClientPoint);
|
||||
mPagePoint = nsDOMEvent::GetPageCoords(aPresContext,
|
||||
aEvent,
|
||||
mRefPoint,
|
||||
mClientPoint);
|
||||
mScreenPoint = nsDOMEvent::GetScreenCoords(aPresContext, aEvent, mRefPoint);
|
||||
mPointsInitialized = true;
|
||||
}
|
||||
void SetTarget(nsIDOMEventTarget *aTarget)
|
||||
{
|
||||
mTarget = aTarget;
|
||||
}
|
||||
bool Equals(nsIDOMTouch* aTouch);
|
||||
protected:
|
||||
nsCOMPtr<nsIDOMEventTarget> mTarget;
|
||||
bool mPointsInitialized;
|
||||
PRInt32 mIdentifier;
|
||||
PRInt32 mPageX;
|
||||
PRInt32 mPageY;
|
||||
PRInt32 mScreenX;
|
||||
PRInt32 mScreenY;
|
||||
PRInt32 mClientX;
|
||||
PRInt32 mClientY;
|
||||
PRInt32 mRadiusX;
|
||||
PRInt32 mRadiusY;
|
||||
nsIntPoint mPagePoint;
|
||||
nsIntPoint mClientPoint;
|
||||
nsIntPoint mScreenPoint;
|
||||
nsIntPoint mRadius;
|
||||
float mRotationAngle;
|
||||
float mForce;
|
||||
};
|
||||
@ -94,25 +133,28 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMTouchList)
|
||||
NS_DECL_NSIDOMTOUCHLIST
|
||||
|
||||
nsDOMTouchList() { }
|
||||
nsDOMTouchList(nsTArray<nsCOMPtr<nsIDOMTouch> > &aTouches);
|
||||
|
||||
void Append(nsIDOMTouch* aPoint)
|
||||
{
|
||||
mPoints.AppendObject(aPoint);
|
||||
mPoints.AppendElement(aPoint);
|
||||
}
|
||||
|
||||
nsIDOMTouch* GetItemAt(PRUint32 aIndex)
|
||||
{
|
||||
return mPoints.SafeObjectAt(aIndex);
|
||||
return mPoints.SafeElementAt(aIndex, nsnull);
|
||||
}
|
||||
protected:
|
||||
nsCOMArray<nsIDOMTouch> mPoints;
|
||||
nsTArray<nsCOMPtr<nsIDOMTouch> > mPoints;
|
||||
};
|
||||
|
||||
class nsDOMTouchEvent : public nsDOMUIEvent,
|
||||
public nsIDOMTouchEvent
|
||||
{
|
||||
public:
|
||||
nsDOMTouchEvent(nsPresContext* aPresContext, nsInputEvent* aEvent);
|
||||
nsDOMTouchEvent(nsPresContext* aPresContext, nsTouchEvent* aEvent);
|
||||
virtual ~nsDOMTouchEvent();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -244,7 +244,18 @@ NS_IMETHODIMP
|
||||
nsDOMUIEvent::GetPageX(PRInt32* aPageX)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPageX);
|
||||
#ifdef MOZ_TOUCH
|
||||
if (mPrivateDataDuplicated) {
|
||||
*aPageX = mPagePoint.x;
|
||||
} else {
|
||||
*aPageX = nsDOMEvent::GetPageCoords(mPresContext,
|
||||
mEvent,
|
||||
mEvent->refPoint,
|
||||
mClientPoint).x;
|
||||
}
|
||||
#else
|
||||
*aPageX = GetPagePoint().x;
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -252,7 +263,18 @@ NS_IMETHODIMP
|
||||
nsDOMUIEvent::GetPageY(PRInt32* aPageY)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPageY);
|
||||
#ifdef MOZ_TOUCH
|
||||
if (mPrivateDataDuplicated) {
|
||||
*aPageY = mPagePoint.y;
|
||||
} else {
|
||||
*aPageY = nsDOMEvent::GetPageCoords(mPresContext,
|
||||
mEvent,
|
||||
mEvent->refPoint,
|
||||
mClientPoint).y;
|
||||
}
|
||||
#else
|
||||
*aPageY = GetPagePoint().y;
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -338,6 +360,7 @@ nsDOMUIEvent::GetLayerPoint()
|
||||
mEvent->eventStructType != NS_POPUP_EVENT &&
|
||||
mEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
|
||||
mEvent->eventStructType != NS_MOZTOUCH_EVENT &&
|
||||
mEvent->eventStructType != NS_TOUCH_EVENT &&
|
||||
mEvent->eventStructType != NS_DRAG_EVENT &&
|
||||
mEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT) ||
|
||||
!mPresContext ||
|
||||
@ -390,11 +413,27 @@ nsDOMUIEvent::GetIsChar(bool* aIsChar)
|
||||
NS_METHOD
|
||||
nsDOMUIEvent::DuplicatePrivateData()
|
||||
{
|
||||
#ifdef MOZ_TOUCH
|
||||
mClientPoint = nsDOMEvent::GetClientCoords(mPresContext,
|
||||
mEvent,
|
||||
mEvent->refPoint,
|
||||
mClientPoint);
|
||||
mLayerPoint = GetLayerPoint();
|
||||
mPagePoint = nsDOMEvent::GetPageCoords(mPresContext,
|
||||
mEvent,
|
||||
mEvent->refPoint,
|
||||
mClientPoint);
|
||||
// GetScreenPoint converts mEvent->refPoint to right coordinates.
|
||||
nsIntPoint screenPoint = nsDOMEvent::GetScreenCoords(mPresContext,
|
||||
mEvent,
|
||||
mEvent->refPoint);
|
||||
#else
|
||||
mClientPoint = GetClientPoint();
|
||||
mLayerPoint = GetLayerPoint();
|
||||
mPagePoint = GetPagePoint();
|
||||
// GetScreenPoint converts mEvent->refPoint to right coordinates.
|
||||
nsIntPoint screenPoint = GetScreenPoint();
|
||||
#endif
|
||||
nsresult rv = nsDOMEvent::DuplicatePrivateData();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mEvent->refPoint = screenPoint;
|
||||
|
@ -68,8 +68,8 @@ public:
|
||||
JSContext* aCx, jsval* aVal);
|
||||
protected:
|
||||
// Internal helper functions
|
||||
nsIntPoint GetClientPoint();
|
||||
nsIntPoint GetScreenPoint();
|
||||
nsIntPoint GetClientPoint();
|
||||
nsIntPoint GetLayerPoint();
|
||||
nsIntPoint GetPagePoint();
|
||||
|
||||
|
@ -808,6 +808,9 @@ nsEventDispatcher::CreateEvent(nsPresContext* aPresContext,
|
||||
case NS_MOZTOUCH_EVENT:
|
||||
return NS_NewDOMMozTouchEvent(aDOMEvent, aPresContext,
|
||||
static_cast<nsMozTouchEvent*>(aEvent));
|
||||
case NS_TOUCH_EVENT:
|
||||
return NS_NewDOMTouchEvent(aDOMEvent, aPresContext,
|
||||
static_cast<nsTouchEvent*>(aEvent));
|
||||
case NS_TRANSITION_EVENT:
|
||||
return NS_NewDOMTransitionEvent(aDOMEvent, aPresContext,
|
||||
static_cast<nsTransitionEvent*>(aEvent));
|
||||
|
@ -130,6 +130,12 @@ _TEST_FILES += \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifeq (android,$(MOZ_WIDGET_TOOLKIT))
|
||||
_TEST_FILES += \
|
||||
test_bug603008.html \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
_CHROME_FILES = \
|
||||
test_bug336682_2.xul \
|
||||
test_bug336682.js \
|
||||
|
524
content/events/test/test_bug603008.html
Normal file
524
content/events/test/test_bug603008.html
Normal file
@ -0,0 +1,524 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=508906
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 603008</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=508906">Mozilla Bug 603008</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.8">
|
||||
|
||||
/** Test for Bug 306008 - Touch* Events **/
|
||||
|
||||
let tests = [], testTarget, parent;
|
||||
|
||||
let touch = {
|
||||
id: 0,
|
||||
point: {x: 0, y: 0},
|
||||
radius: {x: 0, y: 0},
|
||||
rotation: 0,
|
||||
force: 0.5,
|
||||
target: null
|
||||
}
|
||||
|
||||
function nextTest() {
|
||||
if (tests.length)
|
||||
SimpleTest.executeSoon(tests.shift());
|
||||
}
|
||||
|
||||
function random() {
|
||||
return Math.floor(Math.random() * 100);
|
||||
}
|
||||
|
||||
function checkEvent(aFakeEvent) {
|
||||
return function(aEvent) {
|
||||
is(aFakeEvent.ctrlKey, aEvent.ctrlKey, "Correct ctrlKey");
|
||||
is(aFakeEvent.altKey, aEvent.altKey, "Correct altKey");
|
||||
is(aFakeEvent.shiftKey, aEvent.shiftKey, "Correct shiftKey");
|
||||
is(aFakeEvent.metaKey, aEvent.metaKey, "Correct metaKey");
|
||||
checkTouches(aFakeEvent.touches, aEvent.touches);
|
||||
checkTouches(aFakeEvent.targetTouches, aEvent.targetTouches);
|
||||
checkTouches(aFakeEvent.changedTouches, aEvent.changedTouches);
|
||||
}
|
||||
}
|
||||
|
||||
function checkTouches(aTouches1, aTouches2) {
|
||||
is(aTouches1.length, aTouches2.length, "Correct touches length");
|
||||
for (var i = 0; i < aTouches1.length; i++) {
|
||||
checkTouch(aTouches1[i], aTouches2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function checkTouch(aFakeTouch, aTouch) {
|
||||
is(aFakeTouch.identifier, aTouch.identifier, "Touch has correct identifier");
|
||||
is(aFakeTouch.target, aTouch.target, "Touch has correct target");
|
||||
is(aFakeTouch.page.x, aTouch.pageX, "Touch has correct pageX");
|
||||
is(aFakeTouch.page.y, aTouch.pageY, "Touch has correct pageY");
|
||||
is(aFakeTouch.page.x + Math.round(window.mozInnerScreenX), aTouch.screenX, "Touch has correct screenX");
|
||||
is(aFakeTouch.page.y + Math.round(window.mozInnerScreenY), aTouch.screenY, "Touch has correct screenY");
|
||||
is(aFakeTouch.page.x, aTouch.clientX, "Touch has correct clientX");
|
||||
is(aFakeTouch.page.y, aTouch.clientY, "Touch has correct clientY");
|
||||
is(aFakeTouch.radius.x, aTouch.radiusX, "Touch has correct radiusX");
|
||||
is(aFakeTouch.radius.y, aTouch.radiusY, "Touch has correct radiusY");
|
||||
is(aFakeTouch.rotationAngle, aTouch.rotationAngle, "Touch has correct rotationAngle");
|
||||
is(aFakeTouch.force, aTouch.force, "Touch has correct force");
|
||||
}
|
||||
|
||||
function sendTouchEvent(windowUtils, aType, aEvent, aModifiers) {
|
||||
var ids = [], xs=[], ys=[], rxs = [], rys = [],
|
||||
rotations = [], forces = [];
|
||||
|
||||
for each (var touchType in ["touches", "changedTouches", "targetTouches"]) {
|
||||
for (var i = 0; i < aEvent[touchType].length; i++) {
|
||||
if (ids.indexOf(aEvent[touchType][i].identifier) == -1) {
|
||||
ids.push(aEvent[touchType][i].identifier);
|
||||
xs.push(aEvent[touchType][i].page.x);
|
||||
ys.push(aEvent[touchType][i].page.y);
|
||||
rxs.push(aEvent[touchType][i].radius.x);
|
||||
rys.push(aEvent[touchType][i].radius.y);
|
||||
rotations.push(aEvent[touchType][i].rotationAngle);
|
||||
forces.push(aEvent[touchType][i].force);
|
||||
}
|
||||
}
|
||||
}
|
||||
return windowUtils.sendTouchEvent(aType,
|
||||
ids, xs, ys, rxs, rys,
|
||||
rotations, forces,
|
||||
ids.length, aModifiers, 0);
|
||||
}
|
||||
|
||||
function touchEvent(aOptions) {
|
||||
if (!aOptions) {
|
||||
aOptions = {};
|
||||
}
|
||||
this.ctrlKey = aOptions.ctrlKey || false;
|
||||
this.altKey = aOptions.altKey || false;
|
||||
this.shiftKey = aOptions.shiftKey || false;
|
||||
this.metaKey = aOptions.metaKey || false;
|
||||
this.touches = aOptions.touches || [];
|
||||
this.targetTouches = aOptions.targetTouches || [];
|
||||
this.changedTouches = aOptions.changedTouches || [];
|
||||
}
|
||||
|
||||
function testtouch(aOptions) {
|
||||
if (!aOptions)
|
||||
aOptions = {};
|
||||
this.identifier = aOptions.identifier || 0;
|
||||
this.target = aOptions.target || 0;
|
||||
this.page = aOptions.page || {x: 0, y: 0};
|
||||
this.radius = aOptions.radius || {x: 0, y: 0};
|
||||
this.rotationAngle = aOptions.rotationAngle || 0;
|
||||
this.force = aOptions.force || 1;
|
||||
}
|
||||
|
||||
function testSingleTouch(name) {
|
||||
let cwu = SpecialPowers.getDOMWindowUtils(window);
|
||||
let target = document.getElementById("testTarget");
|
||||
let target2 = document.getElementById("testTarget2");
|
||||
let bcr = target.getBoundingClientRect();
|
||||
let bcr2 = target2.getBoundingClientRect();
|
||||
|
||||
let touch1 = new testtouch({
|
||||
page: {x: Math.round(bcr.left + bcr.width/2),
|
||||
y: Math.round(bcr.top + bcr.height/2)},
|
||||
target: target
|
||||
});
|
||||
let event = new touchEvent({
|
||||
touches: [touch1],
|
||||
targetTouches: [touch1],
|
||||
changedTouches: [touch1]
|
||||
});
|
||||
|
||||
// test touchstart event fires correctly
|
||||
var checkFunction = checkEvent(event);
|
||||
window.addEventListener("touchstart", checkFunction, false);
|
||||
sendTouchEvent(cwu, "touchstart", event, 0);
|
||||
window.removeEventListener("touchstart", checkFunction, false);
|
||||
|
||||
// test touchmove event fires correctly
|
||||
event.touches[0].page.x -= 1;
|
||||
event.targetTouches[0].page.x -= 1;
|
||||
event.changedTouches[0].page.x -= 1;
|
||||
checkFunction = checkEvent(event);
|
||||
window.addEventListener("touchmove", checkFunction, false);
|
||||
sendTouchEvent(cwu, "touchmove", event, 0);
|
||||
window.removeEventListener("touchmove", checkFunction, false);
|
||||
|
||||
// test touchend event fires correctly
|
||||
event.touches = [];
|
||||
event.targetTouches = [];
|
||||
checkFunction = checkEvent(event);
|
||||
window.addEventListener("touchend", checkFunction, false);
|
||||
sendTouchEvent(cwu, "touchend", event, 0);
|
||||
window.removeEventListener("touchend", checkFunction, false);
|
||||
|
||||
nextTest();
|
||||
}
|
||||
|
||||
function testSingleTouch2(name) {
|
||||
// firing a touchstart that includes only one touch will evict any touches in the queue with touchend messages
|
||||
let cwu = SpecialPowers.getDOMWindowUtils(window);
|
||||
let target = document.getElementById("testTarget");
|
||||
let target2 = document.getElementById("testTarget2");
|
||||
let bcr = target.getBoundingClientRect();
|
||||
let bcr2 = target2.getBoundingClientRect();
|
||||
|
||||
let touch1 = new testtouch({
|
||||
identifier: 0,
|
||||
page: {x: Math.round(bcr.left + bcr.width/2),
|
||||
y: Math.round(bcr.top + bcr.height/2)},
|
||||
target: target
|
||||
});
|
||||
let event1 = new touchEvent({
|
||||
touches: [touch1],
|
||||
targetTouches: [touch1],
|
||||
changedTouches: [touch1]
|
||||
});
|
||||
let touch2 = new testtouch({
|
||||
identifier: 1,
|
||||
page: {x: Math.round(bcr2.left + bcr2.width/2),
|
||||
y: Math.round(bcr2.top + bcr2.height/2)},
|
||||
target: target2
|
||||
});
|
||||
let event2 = new touchEvent({
|
||||
touches: [touch2],
|
||||
targetTouches: [touch2],
|
||||
changedTouches: [touch2]
|
||||
});
|
||||
|
||||
// test touchstart event fires correctly
|
||||
var checkFunction1 = checkEvent(event1);
|
||||
window.addEventListener("touchstart", checkFunction1, false);
|
||||
sendTouchEvent(cwu, "touchstart", event1, 0);
|
||||
window.removeEventListener("touchstart", checkFunction1, false);
|
||||
|
||||
event1.touches = [];
|
||||
event1.targetTouches = [];
|
||||
checkFunction1 = checkEvent(event1);
|
||||
var checkFunction2 = checkEvent(event2);
|
||||
|
||||
window.addEventListener("touchend", checkFunction1, false);
|
||||
window.addEventListener("touchstart", checkFunction2, false);
|
||||
sendTouchEvent(cwu, "touchstart", event2, 0);
|
||||
window.removeEventListener("touchend", checkFunction1, false);
|
||||
window.removeEventListener("touchstart", checkFunction2, false);
|
||||
|
||||
sendTouchEvent(cwu, "touchstart", event1, 0);
|
||||
|
||||
nextTest();
|
||||
}
|
||||
|
||||
|
||||
function testMultiTouch(name) {
|
||||
let cwu = SpecialPowers.getDOMWindowUtils(window);
|
||||
let target1 = document.getElementById("testTarget");
|
||||
let target2 = document.getElementById("testTarget2");
|
||||
let bcr = target1.getBoundingClientRect();
|
||||
let bcr2 = target2.getBoundingClientRect();
|
||||
|
||||
let touch1 = new testtouch({
|
||||
identifier: 0,
|
||||
page: {x: Math.round(bcr.left + bcr.width/2),
|
||||
y: Math.round(bcr.top + bcr.height/2)},
|
||||
target: target1
|
||||
});
|
||||
let touch2 = new testtouch({
|
||||
identifier: 1,
|
||||
page: {x: Math.round(bcr2.left + bcr2.width/2),
|
||||
y: Math.round(bcr2.top + bcr2.height/2)},
|
||||
target: target2
|
||||
});
|
||||
let event = new touchEvent({
|
||||
touches: [touch1],
|
||||
targetTouches: [touch1],
|
||||
changedTouches: [touch1]
|
||||
});
|
||||
|
||||
// test touchstart event fires correctly
|
||||
var checkFunction = checkEvent(event);
|
||||
window.addEventListener("touchstart", checkFunction, false);
|
||||
sendTouchEvent(cwu, "touchstart", event, 0);
|
||||
window.removeEventListener("touchstart", checkFunction, false);
|
||||
|
||||
event.touches.push(touch2);
|
||||
event.targetTouches = [touch2];
|
||||
event.changedTouches = [touch2];
|
||||
window.addEventListener("touchstart", checkFunction, false);
|
||||
sendTouchEvent(cwu, "touchstart", event, 0);
|
||||
window.removeEventListener("touchstart", checkFunction, false);
|
||||
|
||||
// test moving one touch point
|
||||
event.touches[0].page.x -= 1;
|
||||
event.targetTouches = [event.touches[0]];
|
||||
event.changedTouches = [event.touches[0]];
|
||||
window.addEventListener("touchmove", checkFunction, false);
|
||||
sendTouchEvent(cwu, "touchmove", event, 0);
|
||||
window.removeEventListener("touchmove", checkFunction, false);
|
||||
|
||||
// test moving both touch points -- two touchmove events should fire, one on each target
|
||||
event.touches[0].page.x -= 1;
|
||||
event.touches[1].page.x -= 1;
|
||||
event.targetTouches = event.touches;
|
||||
event.changedTouches = event.touches;
|
||||
var touchMoveEvents = 0;
|
||||
var checkFunction2 = function(aEvent) {
|
||||
is(event.ctrlKey, aEvent.ctrlKey, "Correct ctrlKey");
|
||||
is(event.altKey, aEvent.altKey, "Correct altKey");
|
||||
is(event.shiftKey, aEvent.shiftKey, "Correct shiftKey");
|
||||
is(event.metaKey, aEvent.metaKey, "Correct metaKey");
|
||||
checkTouches(event.touches, aEvent.touches);
|
||||
checkTouches(event.changedTouches, aEvent.changedTouches);
|
||||
if (aEvent.targetTouches[0].target == target1) {
|
||||
checkTouches([event.touches[0]], aEvent.targetTouches);
|
||||
} else if (aEvent.targetTouches[0].target == target2) {
|
||||
checkTouches([event.touches[1]], aEvent.targetTouches);
|
||||
} else
|
||||
ok(false, "Event target is incorrect: " + event.targetTouches[0].target.nodeName + "#" + event.targetTouches[0].target.id);
|
||||
touchMoveEvents++;
|
||||
};
|
||||
window.addEventListener("touchmove", checkFunction2, false);
|
||||
sendTouchEvent(cwu, "touchmove", event, 0);
|
||||
ok(touchMoveEvents, 2, "Correct number of touchmove events fired");
|
||||
window.removeEventListener("touchmove", checkFunction2, false);
|
||||
|
||||
// test removing just one finger
|
||||
var expected = new touchEvent({
|
||||
touches: [touch2],
|
||||
targetTouches: [],
|
||||
changedTouches: [touch1]
|
||||
});
|
||||
checkFunction = checkEvent(expected);
|
||||
|
||||
event.touches = [];
|
||||
event.targetTouches = [];
|
||||
event.changedTouches = [touch1];
|
||||
|
||||
// test removing the other finger
|
||||
window.addEventListener("touchend", checkFunction, false);
|
||||
sendTouchEvent(cwu, "touchend", event, 0);
|
||||
window.removeEventListener("touchend", checkFunction, false);
|
||||
|
||||
event.touches = [];
|
||||
event.targetTouches = [];
|
||||
event.changedTouches = [touch2];
|
||||
checkFunction = checkEvent(event);
|
||||
window.addEventListener("touchend", checkFunction, false);
|
||||
sendTouchEvent(cwu, "touchend", event, 0);
|
||||
window.removeEventListener("touchend", checkFunction, false);
|
||||
|
||||
nextTest();
|
||||
}
|
||||
|
||||
function testTouchChanged() {
|
||||
let cwu = SpecialPowers.getDOMWindowUtils(window);
|
||||
let target1 = document.getElementById("testTarget");
|
||||
let bcr = target1.getBoundingClientRect();
|
||||
|
||||
let touch1 = new testtouch({
|
||||
identifier: 0,
|
||||
page: {x: Math.round(bcr.left + bcr.width/2),
|
||||
y: Math.round(bcr.top + bcr.height/2)},
|
||||
target: target1
|
||||
});
|
||||
let event = new touchEvent({
|
||||
touches: [touch1],
|
||||
targetTouches: [touch1],
|
||||
changedTouches: [touch1]
|
||||
});
|
||||
|
||||
var checkFunction = checkEvent(event);
|
||||
sendTouchEvent(cwu, "touchstart", event, 0);
|
||||
|
||||
var moveEvents = 0;
|
||||
function onMove(aEvent) {
|
||||
moveEvents++;
|
||||
}
|
||||
|
||||
window.addEventListener("touchmove", onMove, false);
|
||||
|
||||
// changing nothing should not fire a touchmove event
|
||||
sendTouchEvent(cwu, "touchmove", event, 0);
|
||||
|
||||
// test moving x
|
||||
event.touches[0].page.x -= 1;
|
||||
sendTouchEvent(cwu, "touchmove", event, 0);
|
||||
|
||||
// test moving y
|
||||
event.touches[0].page.y -= 1;
|
||||
sendTouchEvent(cwu, "touchmove", event, 0);
|
||||
|
||||
// test changing y radius
|
||||
event.touches[0].radius.y += 1;
|
||||
sendTouchEvent(cwu, "touchmove", event, 0);
|
||||
|
||||
// test changing x radius
|
||||
event.touches[0].radius.x += 1;
|
||||
sendTouchEvent(cwu, "touchmove", event, 0);
|
||||
|
||||
// test changing rotationAngle
|
||||
event.touches[0].rotationAngle += 1;
|
||||
sendTouchEvent(cwu, "touchmove", event, 0);
|
||||
|
||||
// test changing force
|
||||
event.touches[0].force += 1;
|
||||
sendTouchEvent(cwu, "touchmove", event, 0);
|
||||
|
||||
// changing nothing again
|
||||
sendTouchEvent(cwu, "touchmove", event, 0);
|
||||
|
||||
is(moveEvents, 6, "Six move events fired");
|
||||
|
||||
window.removeEventListener("touchmove", onMove, false);
|
||||
sendTouchEvent(cwu, "touchend", event, 0);
|
||||
nextTest();
|
||||
}
|
||||
|
||||
function testPreventDefault() {
|
||||
let cwu = SpecialPowers.getDOMWindowUtils(window);
|
||||
let target = document.getElementById("testTarget");
|
||||
let target2 = document.getElementById("testTarget2");
|
||||
let bcr = target.getBoundingClientRect();
|
||||
let bcr2 = target2.getBoundingClientRect();
|
||||
|
||||
let touch1 = new testtouch({
|
||||
page: {x: bcr.left + bcr.width/2,
|
||||
y: bcr.top + bcr.height/2},
|
||||
target: target
|
||||
});
|
||||
let event = new touchEvent({
|
||||
touches: [touch1],
|
||||
targetTouches: [touch1],
|
||||
changedTouches: [touch1]
|
||||
});
|
||||
|
||||
let preventFunction = function(aEvent) {
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
|
||||
let tests = [
|
||||
[{ name: "touchstart", prevent: false },
|
||||
{ name: "touchmove", prevent: false },
|
||||
{ name: "touchmove", prevent: false },
|
||||
{ name: "touchend", prevent: false }],
|
||||
[{ name: "touchstart", prevent: true, doPrevent: true },
|
||||
{ name: "touchmove", prevent: true },
|
||||
{ name: "touchmove", prevent: true },
|
||||
{ name: "touchend", prevent: true }],
|
||||
[{ name: "touchstart", prevent: false },
|
||||
{ name: "touchmove", prevent: true, doPrevent: true },
|
||||
{ name: "touchmove", prevent: true },
|
||||
{ name: "touchend", prevent: true }],
|
||||
[{ name: "touchstart", prevent: false },
|
||||
{ name: "touchmove", prevent: false },
|
||||
{ name: "touchmove", prevent: false, doPrevent: true },
|
||||
{ name: "touchend", prevent: false }],
|
||||
[{ name: "touchstart", prevent: false },
|
||||
{ name: "touchmove", prevent: false },
|
||||
{ name: "touchmove", prevent: false },
|
||||
{ name: "touchend", prevent: false, doPrevent: true }]
|
||||
];
|
||||
|
||||
var dotest = function(aTest) {
|
||||
if (aTest.doPrevent) {
|
||||
target.addEventListener(aTest.name, preventFunction, false);
|
||||
}
|
||||
|
||||
if (aTest.name == "touchmove") {
|
||||
touch1.page.x++;
|
||||
event.touches[0] = touch1;
|
||||
}
|
||||
|
||||
is(sendTouchEvent(cwu, aTest.name, event, 0), aTest.prevent, "Got correct status");
|
||||
|
||||
if (aTest.doPrevent)
|
||||
target.removeEventListener(aTest.name, preventFunction, false);
|
||||
}
|
||||
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
for (var j = 0; j < tests[i].length; j++) {
|
||||
dotest(tests[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
nextTest();
|
||||
}
|
||||
|
||||
function testRemovingElement() {
|
||||
let cwu = SpecialPowers.getDOMWindowUtils(window);
|
||||
let target = document.getElementById("testTarget");
|
||||
let bcr = document.getElementById("testTarget").getBoundingClientRect();
|
||||
|
||||
let touch1 = new testtouch({
|
||||
page: {x: bcr.left + bcr.width/2,
|
||||
y: bcr.top + bcr.height/2},
|
||||
});
|
||||
let e = new touchEvent({
|
||||
touches: [touch1],
|
||||
targetTouches: [touch1],
|
||||
changedTouches: [touch1]
|
||||
});
|
||||
|
||||
var touchEvents = 0;
|
||||
var removeTarget = function(aEvent) {
|
||||
aEvent.target.parentNode.removeChild(aEvent.target);
|
||||
};
|
||||
|
||||
var checkTarget = function(aEvent) {
|
||||
is(aEvent.target, target, "Event has correct target");
|
||||
touchEvents++;
|
||||
};
|
||||
|
||||
target.addEventListener("touchstart", removeTarget, false);
|
||||
target.addEventListener("touchmove", checkTarget, false);
|
||||
target.addEventListener("touchend", checkTarget, false);
|
||||
|
||||
sendTouchEvent(cwu, "touchstart", e, 0);
|
||||
|
||||
e.touches[0].page.x++;
|
||||
sendTouchEvent(cwu, "touchmove", e, 0);
|
||||
sendTouchEvent(cwu, "touchend", e, 0);
|
||||
|
||||
target.removeEventListener("touchstart", removeTarget, false);
|
||||
target.removeEventListener("touchmove", checkTarget, false);
|
||||
target.removeEventListener("touchend", checkTarget, false);
|
||||
|
||||
is(touchEvents, 2, "Check target was called twice");
|
||||
|
||||
nextTest();
|
||||
}
|
||||
|
||||
function doTest() {
|
||||
tests.push(testSingleTouch);
|
||||
tests.push(testSingleTouch2);
|
||||
tests.push(testMultiTouch);
|
||||
tests.push(testPreventDefault);
|
||||
tests.push(testTouchChanged);
|
||||
tests.push(testRemovingElement);
|
||||
|
||||
tests.push(function() {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
nextTest();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(doTest);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
<div id="parent">
|
||||
<span id="testTarget" style="padding: 5px; border: 1px solid black;">testTarget</span>
|
||||
<span id="testTarget2" style="padding: 5px; border: 1px solid blue;">testTarget</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -49,6 +49,8 @@
|
||||
#include "nsEventStateManager.h"
|
||||
#include "nsFrameManager.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
#include "nsDOMTouchEvent.h"
|
||||
#include "nsIDOMTouchEvent.h"
|
||||
|
||||
#include "nsIScrollableFrame.h"
|
||||
|
||||
@ -550,6 +552,79 @@ nsDOMWindowUtils::SendMouseScrollEvent(const nsAString& aType,
|
||||
return widget->DispatchEvent(&event, status);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SendTouchEvent(const nsAString& aType,
|
||||
PRUint32 *aIdentifiers,
|
||||
PRInt32 *aXs,
|
||||
PRInt32 *aYs,
|
||||
PRUint32 *aRxs,
|
||||
PRUint32 *aRys,
|
||||
float *aRotationAngles,
|
||||
float *aForces,
|
||||
PRUint32 aCount,
|
||||
PRInt32 aModifiers,
|
||||
bool aIgnoreRootScrollFrame,
|
||||
bool *aPreventDefault)
|
||||
{
|
||||
if (!IsUniversalXPConnectCapable()) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
// get the widget to send the event to
|
||||
nsPoint offset;
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
|
||||
if (!widget) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
PRInt32 msg;
|
||||
if (aType.EqualsLiteral("touchstart")) {
|
||||
msg = NS_TOUCH_START;
|
||||
} else if (aType.EqualsLiteral("touchmove")) {
|
||||
msg = NS_TOUCH_MOVE;
|
||||
} else if (aType.EqualsLiteral("touchend")) {
|
||||
msg = NS_TOUCH_END;
|
||||
} else if (aType.EqualsLiteral("touchcancel")) {
|
||||
msg = NS_TOUCH_CANCEL;
|
||||
} else {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
nsTouchEvent event(true, msg, widget);
|
||||
event.isShift = (aModifiers & nsIDOMNSEvent::SHIFT_MASK) ? true : false;
|
||||
event.isControl = (aModifiers & nsIDOMNSEvent::CONTROL_MASK) ? true : false;
|
||||
event.isAlt = (aModifiers & nsIDOMNSEvent::ALT_MASK) ? true : false;
|
||||
event.isMeta = (aModifiers & nsIDOMNSEvent::META_MASK) ? true : false;
|
||||
event.widget = widget;
|
||||
event.time = PR_Now();
|
||||
|
||||
nsPresContext* presContext = GetPresContext();
|
||||
if (!presContext) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
event.touches.SetCapacity(aCount);
|
||||
PRInt32 appPerDev = presContext->AppUnitsPerDevPixel();
|
||||
for (int i = 0; i < aCount; ++i) {
|
||||
nsIntPoint pt(0, 0);
|
||||
pt.x =
|
||||
NSAppUnitsToIntPixels(nsPresContext::CSSPixelsToAppUnits(aXs[i]) + offset.x,
|
||||
appPerDev);
|
||||
pt.y =
|
||||
NSAppUnitsToIntPixels(nsPresContext::CSSPixelsToAppUnits(aYs[i]) + offset.y,
|
||||
appPerDev);
|
||||
nsCOMPtr<nsIDOMTouch> t(new nsDOMTouch(aIdentifiers[i],
|
||||
pt,
|
||||
nsIntPoint(aRxs[i], aRys[i]),
|
||||
aRotationAngles[i],
|
||||
aForces[i]));
|
||||
event.touches.AppendElement(t);
|
||||
}
|
||||
|
||||
nsEventStatus status;
|
||||
nsresult rv = widget->DispatchEvent(&event, status);
|
||||
*aPreventDefault = (status == nsEventStatus_eConsumeNoDefault);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SendKeyEvent(const nsAString& aType,
|
||||
PRInt32 aKeyCode,
|
||||
|
@ -68,8 +68,9 @@ interface nsIDOMWindow;
|
||||
interface nsIDOMBlob;
|
||||
interface nsIDOMFile;
|
||||
interface nsIFile;
|
||||
interface nsIDOMTouch;
|
||||
|
||||
[scriptable, uuid(b9c1f815-c2f2-4607-a060-6a8566581927)]
|
||||
[scriptable, uuid(e01171b0-712a-47ce-8552-b7b2ef0a2507)]
|
||||
interface nsIDOMWindowUtils : nsISupports {
|
||||
|
||||
/**
|
||||
@ -227,6 +228,45 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
in long aModifiers,
|
||||
[optional] in boolean aIgnoreRootScrollFrame);
|
||||
|
||||
/** Synthesize a touch event. The event types supported are:
|
||||
* touchstart, touchend, touchmove, and touchcancel
|
||||
*
|
||||
* Events are sent in coordinates offset by aX and aY from the window.
|
||||
*
|
||||
* Cannot be accessed from unprivileged context (not content-accessible)
|
||||
* Will throw a DOM security error if called without UniversalXPConnect
|
||||
* privileges.
|
||||
*
|
||||
* The event is dispatched via the toplevel window, so it could go to any
|
||||
* window under the toplevel window, in some cases it could never reach this
|
||||
* window at all.
|
||||
*
|
||||
* @param aType event type
|
||||
* @param xs array of offsets in CSS pixels for each touch to be sent
|
||||
* @param ys array of offsets in CSS pixels for each touch to be sent
|
||||
* @param rxs array of radii in CSS pixels for each touch to be sent
|
||||
* @param rys array of radii in CSS pixels for each touch to be sent
|
||||
* @param rotationAngles array of angles in degrees for each touch to be sent
|
||||
* @param forces array of forces (floats from 0 to 1) for each touch to be sent
|
||||
* @param count number of touches in this set
|
||||
* @param aModifiers modifiers pressed, using constants defined in nsIDOMNSEvent
|
||||
* @param aIgnoreRootScrollFrame whether the event should ignore viewport bounds
|
||||
* during dispatch
|
||||
*
|
||||
* returns true if the page called prevent default on this touch event
|
||||
*/
|
||||
boolean sendTouchEvent(in AString aType,
|
||||
[array, size_is(count)] in PRUint32 aIdentifiers,
|
||||
[array, size_is(count)] in PRInt32 aXs,
|
||||
[array, size_is(count)] in PRInt32 aYs,
|
||||
[array, size_is(count)] in PRUint32 aRxs,
|
||||
[array, size_is(count)] in PRUint32 aRys,
|
||||
[array, size_is(count)] in float aRotationAngles,
|
||||
[array, size_is(count)] in float aForces,
|
||||
in PRUint32 count,
|
||||
in long aModifiers,
|
||||
[optional] in boolean aIgnoreRootScrollFrame);
|
||||
|
||||
/** The same as sendMouseEvent but ensures that the event is dispatched to
|
||||
* this DOM window or one of its children.
|
||||
*/
|
||||
|
@ -36,13 +36,17 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIDOMUIEvent.idl"
|
||||
%{C++
|
||||
#include "nsWeakPtr.h"
|
||||
#include "nsPoint.h"
|
||||
%}
|
||||
interface nsIVariant;
|
||||
|
||||
/**
|
||||
* @see http://dvcs.w3.org/hg/webevents/raw-file/tip/touchevents.html
|
||||
*/
|
||||
|
||||
[scriptable, uuid(98bc0f7d-5bff-4387-9c42-58af54b48dd5)]
|
||||
[scriptable, builtinclass, uuid(98bc0f7d-5bff-4387-9c42-58af54b48dd5)]
|
||||
interface nsIDOMTouch : nsISupports {
|
||||
readonly attribute long identifier;
|
||||
readonly attribute nsIDOMEventTarget target;
|
||||
@ -56,6 +60,14 @@ interface nsIDOMTouch : nsISupports {
|
||||
readonly attribute long radiusY;
|
||||
readonly attribute float rotationAngle;
|
||||
readonly attribute float force;
|
||||
%{C++
|
||||
nsCOMPtr<nsIDOMEventTarget> mTarget;
|
||||
nsIDOMEventTarget *GetTarget() { return mTarget; }
|
||||
void SetTarget(nsIDOMEventTarget *target) { mTarget = target; }
|
||||
nsIntPoint mRefPoint;
|
||||
bool mChanged;
|
||||
PRUint32 mMessage;
|
||||
%}
|
||||
};
|
||||
|
||||
[scriptable, uuid(60706eb7-d50d-4379-b01c-e78e6af84213)]
|
||||
|
@ -69,6 +69,8 @@
|
||||
#include "nsWeakReference.h"
|
||||
#include <stdio.h> // for FILE definition
|
||||
#include "nsChangeHint.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
|
||||
class nsIContent;
|
||||
class nsIDocument;
|
||||
@ -1047,6 +1049,9 @@ public:
|
||||
|
||||
static CapturingContentInfo gCaptureInfo;
|
||||
|
||||
static nsInterfaceHashtable<nsUint32HashKey, nsIDOMTouch> gCaptureTouchList;
|
||||
static bool gPreventMouseEvents;
|
||||
|
||||
/**
|
||||
* When capturing content is set, it traps all mouse events and retargets
|
||||
* them at this content node. If capturing is not allowed
|
||||
|
@ -956,13 +956,20 @@ nsLayoutUtils::GetEventCoordinatesRelativeTo(const nsEvent* aEvent, nsIFrame* aF
|
||||
aEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT &&
|
||||
aEvent->eventStructType != NS_GESTURENOTIFY_EVENT &&
|
||||
aEvent->eventStructType != NS_MOZTOUCH_EVENT &&
|
||||
#ifdef MOZ_TOUCH
|
||||
aEvent->eventStructType != NS_TOUCH_EVENT &&
|
||||
#endif
|
||||
aEvent->eventStructType != NS_QUERY_CONTENT_EVENT))
|
||||
return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
|
||||
|
||||
const nsGUIEvent* GUIEvent = static_cast<const nsGUIEvent*>(aEvent);
|
||||
#ifdef MOZ_TOUCH
|
||||
return GetEventCoordinatesRelativeTo(aEvent,
|
||||
GUIEvent->refPoint,
|
||||
aFrame);
|
||||
#else
|
||||
if (!GUIEvent->widget)
|
||||
return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
|
||||
|
||||
/* If we walk up the frame tree and discover that any of the frames are
|
||||
* transformed, we need to do extra work to convert from the global
|
||||
* space to the local space.
|
||||
@ -973,7 +980,6 @@ nsLayoutUtils::GetEventCoordinatesRelativeTo(const nsEvent* aEvent, nsIFrame* aF
|
||||
for (nsIFrame* f = aFrame; f; f = GetCrossDocParentFrame(f)) {
|
||||
if (f->IsTransformed())
|
||||
transformFound = true;
|
||||
|
||||
rootFrame = f;
|
||||
}
|
||||
|
||||
@ -1004,6 +1010,68 @@ nsLayoutUtils::GetEventCoordinatesRelativeTo(const nsEvent* aEvent, nsIFrame* aF
|
||||
* so we can just subtract out the different.
|
||||
*/
|
||||
return widgetToView - aFrame->GetOffsetToCrossDoc(rootFrame);
|
||||
#endif
|
||||
}
|
||||
|
||||
nsPoint
|
||||
nsLayoutUtils::GetEventCoordinatesRelativeTo(const nsEvent* aEvent,
|
||||
const nsIntPoint aPoint,
|
||||
nsIFrame* aFrame)
|
||||
{
|
||||
if (!aFrame) {
|
||||
return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
|
||||
}
|
||||
|
||||
const nsGUIEvent* GUIEvent = static_cast<const nsGUIEvent*>(aEvent);
|
||||
nsIWidget* widget = GUIEvent->widget;
|
||||
if (!widget) {
|
||||
return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
|
||||
}
|
||||
|
||||
/* If we walk up the frame tree and discover that any of the frames are
|
||||
* transformed, we need to do extra work to convert from the global
|
||||
* space to the local space.
|
||||
*/
|
||||
nsIFrame* rootFrame = aFrame;
|
||||
bool transformFound = false;
|
||||
for (nsIFrame* f = aFrame; f; f = GetCrossDocParentFrame(f)) {
|
||||
if (f->IsTransformed()) {
|
||||
transformFound = true;
|
||||
}
|
||||
|
||||
rootFrame = f;
|
||||
}
|
||||
|
||||
nsIView* rootView = rootFrame->GetView();
|
||||
if (!rootView) {
|
||||
return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
|
||||
}
|
||||
|
||||
nsPoint widgetToView = TranslateWidgetToView(rootFrame->PresContext(),
|
||||
widget, aPoint, rootView);
|
||||
|
||||
if (widgetToView == nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)) {
|
||||
return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
|
||||
}
|
||||
|
||||
// Convert from root document app units to app units of the document aFrame
|
||||
// is in.
|
||||
PRInt32 rootAPD = rootFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
PRInt32 localAPD = aFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
widgetToView = widgetToView.ConvertAppUnits(rootAPD, localAPD);
|
||||
|
||||
/* If we encountered a transform, we can't do simple arithmetic to figure
|
||||
* out how to convert back to aFrame's coordinates and must use the CTM.
|
||||
*/
|
||||
if (transformFound) {
|
||||
return TransformRootPointToFrame(aFrame, widgetToView);
|
||||
}
|
||||
|
||||
/* Otherwise, all coordinate systems are translations of one another,
|
||||
* so we can just subtract out the different.
|
||||
*/
|
||||
nsPoint offset = aFrame->GetOffsetToCrossDoc(rootFrame);
|
||||
return widgetToView - offset;
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
|
@ -425,6 +425,20 @@ public:
|
||||
static nsPoint GetEventCoordinatesRelativeTo(const nsEvent* aEvent,
|
||||
nsIFrame* aFrame);
|
||||
|
||||
/**
|
||||
* Get the coordinates of a given point relative to an event and a
|
||||
* given frame.
|
||||
* @param aEvent the event
|
||||
* @param aPoint the point to get the coordinates relative to
|
||||
* @param aFrame the frame to make coordinates relative to
|
||||
* @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
|
||||
* for some reason the coordinates for the mouse are not known (e.g.,
|
||||
* the event is not a GUI event).
|
||||
*/
|
||||
static nsPoint GetEventCoordinatesRelativeTo(const nsEvent* aEvent,
|
||||
const nsIntPoint aPoint,
|
||||
nsIFrame* aFrame);
|
||||
|
||||
/**
|
||||
* Get the popup frame of a given native mouse event.
|
||||
* @param aPresContext only check popups within aPresContext or a descendant
|
||||
|
@ -119,6 +119,7 @@
|
||||
#include "nsILineIterator.h" // for ScrollContentIntoView
|
||||
#include "nsWeakPtr.h"
|
||||
#include "pldhash.h"
|
||||
#include "nsDOMTouchEvent.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIDocShell.h" // for reflow observation
|
||||
#include "nsIBaseWindow.h"
|
||||
@ -235,6 +236,8 @@ CapturingContentInfo nsIPresShell::gCaptureInfo =
|
||||
{ false /* mAllowed */, false /* mRetargetToElement */,
|
||||
false /* mPreventDrag */, nsnull /* mContent */ };
|
||||
nsIContent* nsIPresShell::gKeyDownTarget;
|
||||
nsInterfaceHashtable<nsUint32HashKey, nsIDOMTouch> nsIPresShell::gCaptureTouchList;
|
||||
bool nsIPresShell::gPreventMouseEvents = false;
|
||||
|
||||
static PRUint32
|
||||
ChangeFlag(PRUint32 aFlags, bool aOnOff, PRUint32 aFlag)
|
||||
@ -5709,6 +5712,54 @@ PresShell::RecordMouseLocation(nsGUIEvent* aEvent)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
EvictTouchPoint(nsCOMPtr<nsIDOMTouch>& aTouch)
|
||||
{
|
||||
nsIWidget *widget = nsnull;
|
||||
// is there an easier/better way to dig out the widget?
|
||||
nsCOMPtr<nsINode> node(do_QueryInterface(aTouch->GetTarget()));
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
nsIDocument* doc = node->GetCurrentDoc();
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
nsIPresShell *presShell = doc->GetShell();
|
||||
if (!presShell) {
|
||||
return;
|
||||
}
|
||||
nsIFrame* frame = presShell->GetRootFrame();
|
||||
if (!frame) {
|
||||
return;
|
||||
}
|
||||
nsPoint *pt = new nsPoint(aTouch->mRefPoint.x, aTouch->mRefPoint.y);
|
||||
widget = frame->GetView()->GetNearestWidget(pt);
|
||||
if (!widget) {
|
||||
return;
|
||||
}
|
||||
nsTouchEvent event(true, NS_TOUCH_END, widget);
|
||||
event.isShift = false;
|
||||
event.isControl = false;
|
||||
event.isAlt = false;
|
||||
event.isMeta = false;
|
||||
event.widget = widget;
|
||||
event.time = PR_IntervalNow();
|
||||
event.touches.AppendElement(aTouch);
|
||||
|
||||
nsEventStatus status;
|
||||
widget->DispatchEvent(&event, status);
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
AppendToTouchList(const PRUint32& aKey, nsCOMPtr<nsIDOMTouch>& aData, void *aTouchList)
|
||||
{
|
||||
nsTArray<nsCOMPtr<nsIDOMTouch> > *touches = static_cast<nsTArray<nsCOMPtr<nsIDOMTouch> > *>(aTouchList);
|
||||
aData->mChanged = false;
|
||||
touches->AppendElement(aData);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PresShell::HandleEvent(nsIFrame *aFrame,
|
||||
nsGUIEvent* aEvent,
|
||||
@ -5921,8 +5972,59 @@ PresShell::HandleEvent(nsIFrame *aFrame,
|
||||
// with a window-level mouse exit event since we want to start sending
|
||||
// mouse out events at the root EventStateManager.
|
||||
if (!captureRetarget && !isWindowLevelMouseExit) {
|
||||
#ifdef MOZ_TOUCH
|
||||
nsPoint eventPoint;
|
||||
if (aEvent->message == NS_TOUCH_START) {
|
||||
// Add any new touches to the queue
|
||||
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
|
||||
// if there is only one touch in this touchstart event, assume that it is
|
||||
// the start of a new touch session and evict any old touches in the
|
||||
// queue
|
||||
if (touchEvent->touches.Length() == 1) {
|
||||
nsTArray<nsCOMPtr<nsIDOMTouch> > touches;
|
||||
gCaptureTouchList.Enumerate(&AppendToTouchList, (void *)&touches);
|
||||
for (PRUint32 i = 0; i < touches.Length(); ++i) {
|
||||
EvictTouchPoint(touches[i]);
|
||||
}
|
||||
}
|
||||
for (PRUint32 i = 0; i < touchEvent->touches.Length(); ++i) {
|
||||
nsIDOMTouch *touch = touchEvent->touches[i];
|
||||
nsDOMTouch *domtouch = static_cast<nsDOMTouch*>(touch);
|
||||
touch->mMessage = aEvent->message;
|
||||
|
||||
PRInt32 id = 0;
|
||||
touch->GetIdentifier(&id);
|
||||
if (!gCaptureTouchList.Get(id, nsnull)) {
|
||||
// This event is a new touch. Mark it as a changedTouch and
|
||||
// add it to the queue.
|
||||
touch->mChanged = true;
|
||||
gCaptureTouchList.Put(id, touch);
|
||||
|
||||
eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, touch->mRefPoint, frame);
|
||||
} else {
|
||||
// This touch is an old touch, we need to ensure that is not
|
||||
// marked as changed and set its target correctly
|
||||
touch->mChanged = false;
|
||||
PRInt32 id;
|
||||
touch->GetIdentifier(&id);
|
||||
|
||||
nsCOMPtr<nsIDOMTouch> oldTouch;
|
||||
gCaptureTouchList.Get(id, getter_AddRefs(oldTouch));
|
||||
if (oldTouch) {
|
||||
nsCOMPtr<nsPIDOMEventTarget> targetPtr;
|
||||
oldTouch->GetTarget(getter_AddRefs(targetPtr));
|
||||
domtouch->SetTarget(targetPtr);
|
||||
gCaptureTouchList.Put(id, touch);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, frame);
|
||||
}
|
||||
#else
|
||||
nsPoint eventPoint
|
||||
= nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, frame);
|
||||
#endif
|
||||
{
|
||||
bool ignoreRootScrollFrame = false;
|
||||
if (aEvent->eventStructType == NS_MOUSE_EVENT) {
|
||||
@ -6322,6 +6424,9 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsEventStatus* aStatus)
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (!NS_EVENT_NEEDS_FRAME(aEvent) || GetCurrentEventFrame()) {
|
||||
#ifdef MOZ_TOUCH
|
||||
bool touchIsNew = false;
|
||||
#endif
|
||||
bool isHandlingUserInput = false;
|
||||
|
||||
// XXX How about IME events and input events for plugins?
|
||||
@ -6364,6 +6469,84 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsEventStatus* aStatus)
|
||||
case NS_MOUSE_BUTTON_UP:
|
||||
isHandlingUserInput = true;
|
||||
break;
|
||||
#ifdef MOZ_TOUCH
|
||||
case NS_TOUCH_CANCEL:
|
||||
case NS_TOUCH_END: {
|
||||
// Remove the changed touches
|
||||
// need to make sure we only remove touches that are ending here
|
||||
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
|
||||
nsTArray<nsCOMPtr<nsIDOMTouch> > &touches = touchEvent->touches;
|
||||
for (PRUint32 i = 0; i < touches.Length(); ++i) {
|
||||
nsIDOMTouch *touch = touches[i];
|
||||
nsDOMTouch *domtouch = static_cast<nsDOMTouch*>(touch);
|
||||
if (!touch) {
|
||||
continue;
|
||||
}
|
||||
touch->mMessage = aEvent->message;
|
||||
touch->mChanged = true;
|
||||
nsCOMPtr<nsIDOMTouch> oldTouch;
|
||||
|
||||
PRInt32 id;
|
||||
touch->GetIdentifier(&id);
|
||||
|
||||
gCaptureTouchList.Get(id, getter_AddRefs(oldTouch));
|
||||
if (!oldTouch) {
|
||||
continue;
|
||||
}
|
||||
nsCOMPtr<nsPIDOMEventTarget> targetPtr;
|
||||
oldTouch->GetTarget(getter_AddRefs(targetPtr));
|
||||
|
||||
mCurrentEventContent = do_QueryInterface(targetPtr);
|
||||
domtouch->SetTarget(targetPtr);
|
||||
gCaptureTouchList.Remove(id);
|
||||
}
|
||||
// add any touches left in the touch list, but ensure changed=false
|
||||
gCaptureTouchList.Enumerate(&AppendToTouchList, (void *)&touches);
|
||||
break;
|
||||
}
|
||||
case NS_TOUCH_MOVE: {
|
||||
// Check for touches that changed. Mark them add to queue
|
||||
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
|
||||
nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
|
||||
bool haveChanged = false;
|
||||
for (PRUint32 i = 0; i < touches.Length(); ++i) {
|
||||
nsIDOMTouch *touch = touches[i];
|
||||
nsDOMTouch *domtouch = static_cast<nsDOMTouch*>(touch);
|
||||
if (!touch) {
|
||||
continue;
|
||||
}
|
||||
PRInt32 id;
|
||||
touch->GetIdentifier(&id);
|
||||
touch->mMessage = aEvent->message;
|
||||
|
||||
nsCOMPtr<nsIDOMTouch> oldTouch;
|
||||
gCaptureTouchList.Get(id, getter_AddRefs(oldTouch));
|
||||
if (!oldTouch) {
|
||||
continue;
|
||||
}
|
||||
if(domtouch->Equals(oldTouch)) {
|
||||
touch->mChanged = true;
|
||||
haveChanged = true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMEventTarget> targetPtr;
|
||||
oldTouch->GetTarget(getter_AddRefs(targetPtr));
|
||||
domtouch->SetTarget(targetPtr);
|
||||
|
||||
gCaptureTouchList.Put(id, touch);
|
||||
// if we're moving from touchstart to touchmove for this touch
|
||||
// we allow preventDefault to prevent mouse events
|
||||
if (oldTouch->mMessage != touch->mMessage) {
|
||||
touchIsNew = true;
|
||||
}
|
||||
}
|
||||
// is nothing has changed, we should just return
|
||||
if (!haveChanged) {
|
||||
return NS_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case NS_DRAGDROP_DROP:
|
||||
nsCOMPtr<nsIDragSession> session = nsContentUtils::GetDragSession();
|
||||
if (session) {
|
||||
@ -6389,7 +6572,7 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsEventStatus* aStatus)
|
||||
if (me->isShift)
|
||||
aEvent->flags |= NS_EVENT_FLAG_ONLY_CHROME_DISPATCH |
|
||||
NS_EVENT_RETARGET_TO_NON_NATIVE_ANONYMOUS;
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoHandlingUserInputStatePusher userInpStatePusher(isHandlingUserInput,
|
||||
aEvent, mDocument);
|
||||
@ -6422,7 +6605,14 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsEventStatus* aStatus)
|
||||
// because they do not have a reliable refPoint.
|
||||
if (!IsSynthesizedMouseEvent(aEvent)) {
|
||||
nsPresShellEventCB eventCB(this);
|
||||
#ifdef MOZ_TOUCH
|
||||
if (aEvent->eventStructType == NS_TOUCH_EVENT) {
|
||||
DispatchTouchEvent(aEvent, aStatus, &eventCB, touchIsNew);
|
||||
}
|
||||
else if (mCurrentEventContent) {
|
||||
#else
|
||||
if (mCurrentEventContent) {
|
||||
#endif
|
||||
nsEventDispatcher::Dispatch(mCurrentEventContent, mPresContext,
|
||||
aEvent, nsnull, aStatus, &eventCB);
|
||||
}
|
||||
@ -6460,6 +6650,98 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsEventStatus* aStatus)
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
PresShell::DispatchTouchEvent(nsEvent *aEvent,
|
||||
nsEventStatus* aStatus,
|
||||
nsPresShellEventCB* aEventCB,
|
||||
bool aTouchIsNew)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
// calling preventDefault on touchstart or the first touchmove for a
|
||||
// point prevents mouse events
|
||||
bool canPrevent = aEvent->message == NS_TOUCH_START ||
|
||||
(aEvent->message == NS_TOUCH_MOVE && aTouchIsNew);
|
||||
bool preventDefault = false;
|
||||
nsEventStatus tmpStatus = nsEventStatus_eIgnore;
|
||||
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
|
||||
// touch events should fire on all targets
|
||||
if (aEvent->message != NS_TOUCH_START) {
|
||||
nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
|
||||
for (PRUint32 i = 0; i < touches.Length(); ++i) {
|
||||
nsIDOMTouch *touch = touches[i];
|
||||
if (!touch || !touch->mChanged) {
|
||||
continue;
|
||||
}
|
||||
// copy the event
|
||||
nsCOMPtr<nsPIDOMEventTarget> targetPtr;
|
||||
touch->GetTarget(getter_AddRefs(targetPtr));
|
||||
if (!targetPtr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsTouchEvent newEvent(touchEvent);
|
||||
newEvent.target = targetPtr;
|
||||
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(targetPtr));
|
||||
nsPresContext *context = nsContentUtils::GetContextForContent(content);
|
||||
if (!context) {
|
||||
context = mPresContext;
|
||||
}
|
||||
tmpStatus = nsEventStatus_eIgnore;
|
||||
nsEventDispatcher::Dispatch(targetPtr, context,
|
||||
&newEvent, nsnull, &tmpStatus, aEventCB);
|
||||
if (nsEventStatus_eConsumeNoDefault == tmpStatus) {
|
||||
preventDefault = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// touchevents need to have the target attribute set on each touch
|
||||
nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
|
||||
for (PRUint32 i = 0; i < touches.Length(); ++i) {
|
||||
nsIDOMTouch *touch = touches[i];
|
||||
if (touch->mChanged) {
|
||||
touch->SetTarget(mCurrentEventContent);
|
||||
}
|
||||
}
|
||||
|
||||
if (mCurrentEventContent) {
|
||||
nsEventDispatcher::Dispatch(mCurrentEventContent, mPresContext,
|
||||
aEvent, nsnull, &tmpStatus, aEventCB);
|
||||
} else {
|
||||
nsCOMPtr<nsIContent> targetContent;
|
||||
rv = mCurrentEventFrame->GetContentForEvent(aEvent,
|
||||
getter_AddRefs(targetContent));
|
||||
if (NS_SUCCEEDED(rv) && targetContent) {
|
||||
nsEventDispatcher::Dispatch(targetContent, mPresContext, aEvent,
|
||||
nsnull, &tmpStatus, aEventCB);
|
||||
} else if (mDocument) {
|
||||
nsEventDispatcher::Dispatch(mDocument, mPresContext, aEvent,
|
||||
nsnull, &tmpStatus, nsnull);
|
||||
}
|
||||
}
|
||||
if (nsEventStatus_eConsumeNoDefault == tmpStatus) {
|
||||
preventDefault = true;
|
||||
}
|
||||
|
||||
if (touchEvent->touches.Length() == 1) {
|
||||
gPreventMouseEvents = false;
|
||||
}
|
||||
}
|
||||
|
||||
// if preventDefault was called on any of the events dispatched
|
||||
// and this is touchstart, or the first touchmove, widget should consume
|
||||
// other events that would be associated with this touch session
|
||||
if (preventDefault && canPrevent) {
|
||||
gPreventMouseEvents = true;
|
||||
}
|
||||
|
||||
if (gPreventMouseEvents) {
|
||||
*aStatus = nsEventStatus_eConsumeNoDefault;
|
||||
} else {
|
||||
*aStatus = nsEventStatus_eIgnore;
|
||||
}
|
||||
}
|
||||
|
||||
// Dispatch event to content only (NOT full processing)
|
||||
// See also HandleEventWithTarget which does full event processing.
|
||||
nsresult
|
||||
@ -8723,6 +9005,7 @@ void nsIPresShell::InitializeStatics()
|
||||
NS_ASSERTION(sLiveShells == nsnull, "InitializeStatics called multiple times!");
|
||||
sLiveShells = new nsTHashtable<PresShellPtrKey>();
|
||||
sLiveShells->Init();
|
||||
gCaptureTouchList.Init();
|
||||
}
|
||||
|
||||
void nsIPresShell::ReleaseStatics()
|
||||
|
@ -459,6 +459,12 @@ protected:
|
||||
nsresult DidCauseReflow();
|
||||
friend class nsAutoCauseReflowNotifier;
|
||||
|
||||
bool TouchesAreEqual(nsIDOMTouch *aTouch1, nsIDOMTouch *aTouch2);
|
||||
void DispatchTouchEvent(nsEvent *aEvent,
|
||||
nsEventStatus* aStatus,
|
||||
nsPresShellEventCB* aEventCB,
|
||||
bool aTouchIsNew);
|
||||
|
||||
void WillDoReflow();
|
||||
void DidDoReflow(bool aInterruptible);
|
||||
// ProcessReflowCommands returns whether we processed all our dirty roots
|
||||
|
@ -147,8 +147,7 @@ static ViewWrapper* GetWrapperFor(nsIWidget* aWidget)
|
||||
static nsEventStatus HandleEvent(nsGUIEvent *aEvent)
|
||||
{
|
||||
#if 0
|
||||
printf(" %d %d %d (%d,%d) \n", aEvent->widget, aEvent->widgetSupports,
|
||||
aEvent->message, aEvent->point.x, aEvent->point.y);
|
||||
printf(" %d %d %d (%d,%d) \n", aEvent->widget, aEvent->message);
|
||||
#endif
|
||||
nsEventStatus result = nsEventStatus_eIgnore;
|
||||
nsView *view = nsView::GetViewFor(aEvent->widget);
|
||||
@ -327,11 +326,13 @@ nsIView* nsIView::GetViewFor(nsIWidget* aWidget)
|
||||
|
||||
ViewWrapper* wrapper = GetWrapperFor(aWidget);
|
||||
|
||||
if (!wrapper)
|
||||
if (!wrapper) {
|
||||
wrapper = GetAttachedWrapperFor(aWidget);
|
||||
}
|
||||
|
||||
if (wrapper)
|
||||
if (wrapper) {
|
||||
return wrapper->GetView();
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
@ -104,6 +104,7 @@ class nsFocusEvent;
|
||||
class nsSelectionEvent;
|
||||
class nsContentCommandEvent;
|
||||
class nsMozTouchEvent;
|
||||
class nsTouchEvent;
|
||||
class nsFormEvent;
|
||||
class nsCommandEvent;
|
||||
class nsUIEvent;
|
||||
|
@ -42,6 +42,7 @@
|
||||
#ifndef nsGUIEvent_h__
|
||||
#define nsGUIEvent_h__
|
||||
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsPoint.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsRegion.h"
|
||||
@ -53,6 +54,7 @@
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
#include "nsIDOMDataTransfer.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOMTouchEvent.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsTArray.h"
|
||||
@ -60,6 +62,7 @@
|
||||
#include "nsITransferable.h"
|
||||
#include "nsIVariant.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -124,6 +127,7 @@ class nsHashKey;
|
||||
#define NS_UISTATECHANGE_EVENT 41
|
||||
#define NS_MOZTOUCH_EVENT 42
|
||||
#define NS_PLUGIN_EVENT 43
|
||||
#define NS_TOUCH_EVENT 44
|
||||
|
||||
// These flags are sort of a mess. They're sort of shared between event
|
||||
// listener flags and event flags, but only some of them. You've been
|
||||
@ -546,6 +550,14 @@ class nsHashKey;
|
||||
#define NS_FULLSCREENCHANGE (NS_FULL_SCREEN_START)
|
||||
#define NS_FULLSCREENERROR (NS_FULL_SCREEN_START + 1)
|
||||
|
||||
#define NS_TOUCH_EVENT_START 5200
|
||||
#define NS_TOUCH_START (NS_TOUCH_EVENT_START)
|
||||
#define NS_TOUCH_MOVE (NS_TOUCH_EVENT_START+1)
|
||||
#define NS_TOUCH_END (NS_TOUCH_EVENT_START+2)
|
||||
#define NS_TOUCH_ENTER (NS_TOUCH_EVENT_START+3)
|
||||
#define NS_TOUCH_LEAVE (NS_TOUCH_EVENT_START+4)
|
||||
#define NS_TOUCH_CANCEL (NS_TOUCH_EVENT_START+5)
|
||||
|
||||
/**
|
||||
* Return status for event processors, nsEventStatus, is defined in
|
||||
* nsEvent.h.
|
||||
@ -1528,6 +1540,31 @@ public:
|
||||
PRUint32 streamId;
|
||||
};
|
||||
|
||||
class nsTouchEvent : public nsInputEvent
|
||||
{
|
||||
public:
|
||||
nsTouchEvent(nsTouchEvent *aEvent)
|
||||
:nsInputEvent(aEvent->flags & NS_EVENT_FLAG_TRUSTED ? true : false,
|
||||
aEvent->message,
|
||||
aEvent->widget,
|
||||
NS_TOUCH_EVENT)
|
||||
{
|
||||
touches.AppendElements(aEvent->touches);
|
||||
MOZ_COUNT_CTOR(nsTouchEvent);
|
||||
}
|
||||
nsTouchEvent(bool isTrusted, PRUint32 msg, nsIWidget* w)
|
||||
: nsInputEvent(isTrusted, msg, w, NS_TOUCH_EVENT)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsTouchEvent);
|
||||
}
|
||||
~nsTouchEvent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsTouchEvent);
|
||||
}
|
||||
|
||||
nsTArray<nsCOMPtr<nsIDOMTouch> > touches;
|
||||
};
|
||||
|
||||
/**
|
||||
* Form event
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user