diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -538,16 +538,21 @@ nsContentUtils::InitializeEventTable() {
     { &nsGkAtoms::onMozMagnifyGestureUpdate,     { NS_SIMPLE_GESTURE_MAGNIFY_UPDATE, EventNameType_None } },
     { &nsGkAtoms::onMozMagnifyGesture,           { NS_SIMPLE_GESTURE_MAGNIFY, EventNameType_None } },
     { &nsGkAtoms::onMozRotateGestureStart,       { NS_SIMPLE_GESTURE_ROTATE_START, EventNameType_None } },
     { &nsGkAtoms::onMozRotateGestureUpdate,      { NS_SIMPLE_GESTURE_ROTATE_UPDATE, EventNameType_None } },
     { &nsGkAtoms::onMozRotateGesture,            { NS_SIMPLE_GESTURE_ROTATE, EventNameType_None } },
     { &nsGkAtoms::onMozTapGesture,               { NS_SIMPLE_GESTURE_TAP, EventNameType_None } },
     { &nsGkAtoms::onMozPressTapGesture,          { NS_SIMPLE_GESTURE_PRESSTAP, EventNameType_None } },
 
+	// Touch gestures
+    { &nsGkAtoms::onMozTouchDown,                { NS_MOZTOUCH_DOWN, EventNameType_None } },
+    { &nsGkAtoms::onMozTouchMove,                { NS_MOZTOUCH_MOVE, EventNameType_None } },
+    { &nsGkAtoms::onMozTouchRelease,             { NS_MOZTOUCH_RELEASE, EventNameType_None } },
+
     { &nsGkAtoms::ontransitionend,               { NS_TRANSITION_END, EventNameType_None }},
   };
 
   sEventTable = new nsDataHashtable<nsISupportsHashKey, EventNameMapping>;
   if (!sEventTable ||
       !sEventTable->Init(int(NS_ARRAY_LENGTH(eventArray) / 0.75) + 1)) {
     delete sEventTable;
     sEventTable = nsnull;
diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1013,16 +1013,20 @@ GK_ATOM(headerCSPReportOnly, "x-content-
 GK_ATOM(xml, "xml")
 GK_ATOM(xmlns, "xmlns")
 GK_ATOM(xmp, "xmp")
 GK_ATOM(xulcontentsgenerated, "xulcontentsgenerated")
 GK_ATOM(yes, "yes")
 GK_ATOM(z_index, "z-index")
 GK_ATOM(zeroDigit, "zero-digit")
 
+GK_ATOM(onMozTouchDown, "onMozTouchDown")
+GK_ATOM(onMozTouchMove, "onMozTouchMove")
+GK_ATOM(onMozTouchRelease, "onMozTouchRelease")
+
 
 #ifdef MOZ_SVG
 GK_ATOM(percentage, "%")
 GK_ATOM(A, "A")
 GK_ATOM(alignment_baseline, "alignment-baseline")
 GK_ATOM(allowReorder, "allowReorder")
 GK_ATOM(altGlyph, "altGlyph")
 GK_ATOM(altGlyphDef, "altGlyphDef")
diff --git a/content/events/public/nsIPrivateDOMEvent.h b/content/events/public/nsIPrivateDOMEvent.h
--- a/content/events/public/nsIPrivateDOMEvent.h
+++ b/content/events/public/nsIPrivateDOMEvent.h
@@ -109,12 +109,14 @@ NS_NewDOMProgressEvent(nsIDOMEvent** aIn
 nsresult
 NS_NewDOMNotifyPaintEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext,
                           nsEvent* aEvent,
                           PRUint32 aEventType = 0,
                           nsInvalidateRequestList* aInvalidateRequests = nsnull);
 nsresult
 NS_NewDOMSimpleGestureEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsSimpleGestureEvent* aEvent);
 nsresult
+NS_NewDOMMozTouchEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsMozTouchEvent* aEvent);
+nsresult
 NS_NewDOMScrollAreaEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsScrollAreaEvent* aEvent);
 nsresult
 NS_NewDOMTransitionEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsTransitionEvent* aEvent);
 #endif // nsIPrivateDOMEvent_h__
diff --git a/content/events/src/Makefile.in b/content/events/src/Makefile.in
--- a/content/events/src/Makefile.in
+++ b/content/events/src/Makefile.in
@@ -74,16 +74,17 @@ CPPSRCS		= \
 		nsEventDispatcher.cpp \
 		nsIMEStateManager.cpp \
 		nsContentEventHandler.cpp \
 		nsEventListenerService.cpp \
 		nsDOMProgressEvent.cpp \
 		nsDOMDataTransfer.cpp \
 		nsDOMNotifyPaintEvent.cpp \
 		nsDOMSimpleGestureEvent.cpp \
+		nsDOMMozTouchEvent.cpp \
 		nsDOMEventTargetHelper.cpp \
 		nsDOMScrollAreaEvent.cpp \
 		nsDOMTransitionEvent.cpp \
 		nsDOMPopStateEvent.cpp \
 		$(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -88,16 +88,19 @@ static const char* const sEventNames[] =
   "MozMagnifyGestureStart",
   "MozMagnifyGestureUpdate",
   "MozMagnifyGesture",
   "MozRotateGestureStart",
   "MozRotateGestureUpdate",
   "MozRotateGesture",
   "MozTapGesture",
   "MozPressTapGesture",
+  "MozTouchDown",
+  "MozTouchMove",
+  "MozTouchRelease"
   "MozScrolledAreaChanged",
   "transitionend"
 };
 
 static char *sPopupAllowedEvents;
 
 
 nsDOMEvent::nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent)
@@ -178,16 +181,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   if (tmp->mEventIsInternal) {
     tmp->mEvent->target = nsnull;
     tmp->mEvent->currentTarget = nsnull;
     tmp->mEvent->originalTarget = nsnull;
     switch (tmp->mEvent->eventStructType) {
       case NS_MOUSE_EVENT:
       case NS_MOUSE_SCROLL_EVENT:
       case NS_SIMPLE_GESTURE_EVENT:
+      case NS_MOZTOUCH_EVENT:
         static_cast<nsMouseEvent_base*>(tmp->mEvent)->relatedTarget = nsnull;
         break;
       case NS_DRAG_EVENT:
         static_cast<nsDragEvent*>(tmp->mEvent)->dataTransfer = nsnull;
         static_cast<nsMouseEvent_base*>(tmp->mEvent)->relatedTarget = nsnull;
         break;
       case NS_MUTATION_EVENT:
         static_cast<nsMutationEvent*>(tmp->mEvent)->mRelatedNode = nsnull;
@@ -205,16 +209,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
   if (tmp->mEventIsInternal) {
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEvent->target)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEvent->currentTarget)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEvent->originalTarget)
     switch (tmp->mEvent->eventStructType) {
       case NS_MOUSE_EVENT:
       case NS_MOUSE_SCROLL_EVENT:
       case NS_SIMPLE_GESTURE_EVENT:
+      case NS_MOZTOUCH_EVENT:
         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->relatedTarget");
         cb.NoteXPCOMChild(
           static_cast<nsMouseEvent_base*>(tmp->mEvent)->relatedTarget);
         break;
       case NS_DRAG_EVENT:
         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->dataTransfer");
         cb.NoteXPCOMChild(
           static_cast<nsDragEvent*>(tmp->mEvent)->dataTransfer);
@@ -702,16 +707,24 @@ nsDOMEvent::SetEventType(const nsAString
       mEvent->message = NS_SIMPLE_GESTURE_ROTATE_UPDATE;
     else if (atom == nsGkAtoms::onMozRotateGesture)
       mEvent->message = NS_SIMPLE_GESTURE_ROTATE;
     else if (atom == nsGkAtoms::onMozPressTapGesture)
       mEvent->message = NS_SIMPLE_GESTURE_PRESSTAP;
     else if (atom == nsGkAtoms::onMozTapGesture)
       mEvent->message = NS_SIMPLE_GESTURE_TAP;
   }
+  else if (mEvent->eventStructType == NS_MOZTOUCH_EVENT) {
+    if (atom == nsGkAtoms::onMozTouchDown)
+      mEvent->message = NS_MOZTOUCH_DOWN;
+    else if (atom == nsGkAtoms::onMozTouchMove)
+      mEvent->message = NS_MOZTOUCH_MOVE;
+    else if (atom == nsGkAtoms::onMozTouchRelease)
+      mEvent->message = NS_MOZTOUCH_RELEASE;
+  }
   else if (mEvent->eventStructType == NS_TRANSITION_EVENT) {
     if (atom == nsGkAtoms::ontransitionend)
       mEvent->message = NS_TRANSITION_END;
   }
 
   if (mEvent->message == NS_USER_DEFINED_EVENT)
     mEvent->userType = atom;
 
@@ -1008,16 +1021,24 @@ NS_METHOD nsDOMEvent::DuplicatePrivateDa
         new nsSimpleGestureEvent(PR_FALSE, msg, nsnull, 0, 0.0);
       NS_ENSURE_TRUE(simpleGestureEvent, NS_ERROR_OUT_OF_MEMORY);
       isInputEvent = PR_TRUE;
       simpleGestureEvent->direction = oldSimpleGestureEvent->direction;
       simpleGestureEvent->delta = oldSimpleGestureEvent->delta;
       newEvent = simpleGestureEvent;
       break;
     }
+    case NS_MOZTOUCH_EVENT:
+    {
+      newEvent = new nsMozTouchEvent(PR_FALSE, msg, nsnull,
+                                     static_cast<nsMozTouchEvent*>(mEvent)->streamId);
+      NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
+      isInputEvent = PR_TRUE;
+      break;
+    }
     case NS_TRANSITION_EVENT:
     {
       nsTransitionEvent* oldTransitionEvent =
         static_cast<nsTransitionEvent*>(mEvent);
       newEvent = new nsTransitionEvent(PR_FALSE, msg,
                                        oldTransitionEvent->propertyName,
                                        oldTransitionEvent->elapsedTime);
       NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
@@ -1506,16 +1527,22 @@ const char* nsDOMEvent::GetEventName(PRU
   case NS_SIMPLE_GESTURE_ROTATE_UPDATE:
     return sEventNames[eDOMEvents_MozRotateGestureUpdate];
   case NS_SIMPLE_GESTURE_ROTATE:
     return sEventNames[eDOMEvents_MozRotateGesture];
   case NS_SIMPLE_GESTURE_TAP:
     return sEventNames[eDOMEvents_MozTapGesture];
   case NS_SIMPLE_GESTURE_PRESSTAP:
     return sEventNames[eDOMEvents_MozPressTapGesture];
+  case NS_MOZTOUCH_DOWN:
+    return sEventNames[eDOMEvents_MozTouchDown];
+  case NS_MOZTOUCH_MOVE:
+    return sEventNames[eDOMEvents_MozTouchMove];
+  case NS_MOZTOUCH_RELEASE:
+    return sEventNames[eDOMEvents_MozTouchRelease];
   case NS_SCROLLEDAREACHANGED:
     return sEventNames[eDOMEvents_MozScrolledAreaChanged];
   case NS_TRANSITION_END:
     return sEventNames[eDOMEvents_transitionend];
   default:
     break;
   }
   // XXXldb We can hit this case for nsEvent objects that we didn't
diff --git a/content/events/src/nsDOMEvent.h b/content/events/src/nsDOMEvent.h
--- a/content/events/src/nsDOMEvent.h
+++ b/content/events/src/nsDOMEvent.h
@@ -166,16 +166,19 @@ public:
     eDOMEvents_MozMagnifyGestureStart,
     eDOMEvents_MozMagnifyGestureUpdate,
     eDOMEvents_MozMagnifyGesture,
     eDOMEvents_MozRotateGestureStart,
     eDOMEvents_MozRotateGestureUpdate,
     eDOMEvents_MozRotateGesture,
     eDOMEvents_MozTapGesture,
     eDOMEvents_MozPressTapGesture,
+    eDOMEvents_MozTouchDown,
+    eDOMEvents_MozTouchMove,
+    eDOMEvents_MozTouchRelease,
     eDOMEvents_MozScrolledAreaChanged,
     eDOMEvents_transitionend
   };
 
   nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent);
   virtual ~nsDOMEvent();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
diff --git a/content/events/src/nsDOMUIEvent.cpp b/content/events/src/nsDOMUIEvent.cpp
--- a/content/events/src/nsDOMUIEvent.cpp
+++ b/content/events/src/nsDOMUIEvent.cpp
@@ -123,16 +123,17 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEve
 
 nsIntPoint
 nsDOMUIEvent::GetScreenPoint()
 {
   if (!mEvent || 
        (mEvent->eventStructType != NS_MOUSE_EVENT &&
         mEvent->eventStructType != NS_POPUP_EVENT &&
         mEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
+        mEvent->eventStructType != NS_MOZTOUCH_EVENT &&
         mEvent->eventStructType != NS_DRAG_EVENT &&
         mEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT)) {
     return nsIntPoint(0, 0);
   }
 
   if (!((nsGUIEvent*)mEvent)->widget ) {
     return mEvent->refPoint;
   }
@@ -146,16 +147,17 @@ nsDOMUIEvent::GetScreenPoint()
 
 nsIntPoint
 nsDOMUIEvent::GetClientPoint()
 {
   if (!mEvent ||
       (mEvent->eventStructType != NS_MOUSE_EVENT &&
        mEvent->eventStructType != NS_POPUP_EVENT &&
        mEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
+       mEvent->eventStructType != NS_MOZTOUCH_EVENT &&
        mEvent->eventStructType != NS_DRAG_EVENT &&
        mEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT) ||
       !mPresContext ||
       !((nsGUIEvent*)mEvent)->widget) {
     return mClientPoint;
   }
 
   nsPoint pt(0, 0);
@@ -313,16 +315,17 @@ nsDOMUIEvent::SetCancelBubble(PRBool aCa
 
 nsIntPoint
 nsDOMUIEvent::GetLayerPoint()
 {
   if (!mEvent ||
       (mEvent->eventStructType != NS_MOUSE_EVENT &&
        mEvent->eventStructType != NS_POPUP_EVENT &&
        mEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
+       mEvent->eventStructType != NS_MOZTOUCH_EVENT &&
        mEvent->eventStructType != NS_DRAG_EVENT &&
        mEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT) ||
       !mPresContext ||
       mEventIsInternal) {
     return mLayerPoint;
   }
   // XXX I'm not really sure this is correct; it's my best shot, though
   nsIFrame* targetFrame;
diff --git a/content/events/src/nsEventDispatcher.cpp b/content/events/src/nsEventDispatcher.cpp
--- a/content/events/src/nsEventDispatcher.cpp
+++ b/content/events/src/nsEventDispatcher.cpp
@@ -717,16 +717,19 @@ nsEventDispatcher::CreateEvent(nsPresCon
 #endif // MOZ_SVG
 
     case NS_COMMAND_EVENT:
       return NS_NewDOMCommandEvent(aDOMEvent, aPresContext,
                                    static_cast<nsCommandEvent*>(aEvent));
     case NS_SIMPLE_GESTURE_EVENT:
       return NS_NewDOMSimpleGestureEvent(aDOMEvent, aPresContext,
                                          static_cast<nsSimpleGestureEvent*>(aEvent));
+    case NS_MOZTOUCH_EVENT:
+      return NS_NewDOMMozTouchEvent(aDOMEvent, aPresContext,
+                                    static_cast<nsMozTouchEvent*>(aEvent));
     case NS_TRANSITION_EVENT:
       return NS_NewDOMTransitionEvent(aDOMEvent, aPresContext,
                                       static_cast<nsTransitionEvent*>(aEvent));
     }
 
     // For all other types of events, create a vanilla event object.
     return NS_NewDOMEvent(aDOMEvent, aPresContext, aEvent);
   }
@@ -786,16 +789,18 @@ nsEventDispatcher::CreateEvent(nsPresCon
   if (aEventType.LowerCaseEqualsLiteral("notifypaintevent"))
     return NS_NewDOMNotifyPaintEvent(aDOMEvent, aPresContext, nsnull);
   if (aEventType.LowerCaseEqualsLiteral("simplegestureevent"))
     return NS_NewDOMSimpleGestureEvent(aDOMEvent, aPresContext, nsnull);
   if (aEventType.LowerCaseEqualsLiteral("beforeunloadevent"))
     return NS_NewDOMBeforeUnloadEvent(aDOMEvent, aPresContext, nsnull);
   if (aEventType.LowerCaseEqualsLiteral("pagetransition"))
     return NS_NewDOMPageTransitionEvent(aDOMEvent, aPresContext, nsnull);
+  if (aEventType.LowerCaseEqualsLiteral("moztouchevent"))
+    return NS_NewDOMMozTouchEvent(aDOMEvent, aPresContext, nsnull);
   if (aEventType.LowerCaseEqualsLiteral("scrollareaevent"))
     return NS_NewDOMScrollAreaEvent(aDOMEvent, aPresContext, nsnull);
   // FIXME: Should get spec to say what the right string is here!  This
   // is probably wrong!
   if (aEventType.LowerCaseEqualsLiteral("transitionevent"))
     return NS_NewDOMTransitionEvent(aDOMEvent, aPresContext, nsnull);
   if (aEventType.LowerCaseEqualsLiteral("popstateevent"))
     return NS_NewDOMPopStateEvent(aDOMEvent, aPresContext, nsnull);
diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -1161,16 +1161,17 @@ nsEventStateManager::PreHandleEvent(nsPr
   case NS_KEY_DOWN:
   case NS_KEY_UP:
     {
       nsIContent* content = GetFocusedContent();
       if (content)
         mCurrentTargetContent = content;
     }
     break;
+
   case NS_MOUSE_SCROLL:
     {
       nsIContent* content = GetFocusedContent();
       if (content)
         mCurrentTargetContent = content;
 
       nsMouseScrollEvent* msEvent = static_cast<nsMouseScrollEvent*>(aEvent);
 
@@ -2423,16 +2424,47 @@ nsEventStateManager::SendLineScrollEvent
   event.isMeta = aEvent->isMeta;
   event.scrollFlags = aEvent->scrollFlags;
   event.delta = aNumLines;
 
   nsEventDispatcher::Dispatch(targetContent, aPresContext, &event, nsnull, aStatus);
 }
 
 void
+nsEventStateManager::SendMozTouchEvent(nsIFrame* aTargetFrame,
+                                       nsMozTouchEvent* aEvent,
+                                       nsPresContext* aPresContext,
+                                       nsEventStatus* aStatus)
+{
+  nsCOMPtr<nsIContent> targetContent = aTargetFrame->GetContent();
+  if (!targetContent) {
+    targetContent = GetFocusedContent();
+    if (!targetContent)
+      return;
+  }
+
+  while (targetContent->IsNodeOfType(nsINode::eTEXT)) {
+    targetContent = targetContent->GetParent();
+  }
+
+  PRBool isTrusted = (aEvent->flags & NS_EVENT_FLAG_TRUSTED) != 0;
+  nsMozTouchEvent event(isTrusted, aEvent->message, nsnull, 0);
+  event.refPoint = aEvent->refPoint;
+  event.widget = aEvent->widget;
+  event.time = aEvent->time;
+  event.isShift = aEvent->isShift;
+  event.isControl = aEvent->isControl;
+  event.isAlt = aEvent->isAlt;
+  event.isMeta = aEvent->isMeta;
+  event.streamId = aEvent->streamId;
+
+  nsEventDispatcher::Dispatch(targetContent, aPresContext, &event, nsnull, aStatus);
+}
+
+void
 nsEventStateManager::SendPixelScrollEvent(nsIFrame* aTargetFrame,
                                           nsMouseScrollEvent* aEvent,
                                           nsPresContext* aPresContext,
                                           nsEventStatus* aStatus)
 {
   nsCOMPtr<nsIContent> targetContent = aTargetFrame->GetContent();
   if (!targetContent) {
     targetContent = GetFocusedContent();
diff --git a/content/events/src/nsEventStateManager.h b/content/events/src/nsEventStateManager.h
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -260,16 +260,20 @@ protected:
                            nsMouseScrollEvent* aEvent,
                            nsPresContext* aPresContext,
                            nsEventStatus* aStatus,
                            PRInt32 aNumLines);
   void SendPixelScrollEvent(nsIFrame* aTargetFrame,
                             nsMouseScrollEvent* aEvent,
                             nsPresContext* aPresContext,
                             nsEventStatus* aStatus);
+  void SendMozTouchEvent(nsIFrame* aTargetFrame,
+                            nsMozTouchEvent* aEvent,
+                            nsPresContext* aPresContext,
+                            nsEventStatus* aStatus);
   nsresult DoScrollText(nsIFrame* aTargetFrame,
                         nsMouseScrollEvent* aMouseEvent,
                         nsIScrollableFrame::ScrollUnit aScrollQuantity,
                         PRBool aAllowScrollSpeedOverride);
   void DoScrollHistory(PRInt32 direction);
   void DoScrollZoom(nsIFrame *aTargetFrame, PRInt32 adjustment);
   nsresult GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv);
   nsresult ChangeTextSize(PRInt32 change);
diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -2428,16 +2428,100 @@ nsHTMLDocument::SetLinkColor(const nsASt
   if (body) {
     body->SetLink(aLinkColor);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsHTMLDocument::GetMultitouchData(PRBool * aEnabled)
+{
+  *aEnabled = PR_FALSE;
+
+  nsPIDOMWindow *window = GetWindow();
+  if (!window)
+    return NS_ERROR_FAILURE;
+
+  nsIDocShell *docshell = window->GetDocShell();
+  if (!docshell)
+    return NS_ERROR_FAILURE;
+
+  nsPresContext *prescontext;
+  
+  docshell->GetPresContext(&prescontext);
+
+  if (!prescontext)
+    return NS_OK;
+
+  nsCOMPtr<nsISupports> container = prescontext->GetContainer();
+  if (!container)
+    return NS_OK;
+
+  nsCOMPtr<nsIBaseWindow> docShellWin = do_QueryInterface(container);
+  nsIWidget* mainWidget = nsnull;
+  docShellWin->GetMainWidget(&mainWidget);
+  mainWidget->IsTouchWindow(aEnabled);
+
+  return NS_OK;
+
+/*  nsPresShellIterator iter(this);
+  nsCOMPtr<nsIPresShell> shell;
+  while ((shell = iter.GetNextShell())) {
+    nsCOMPtr<nsISupports> container = shell->GetPresContext()->GetContainer();
+    if (!container)
+      continue;
+
+    nsCOMPtr<nsIBaseWindow> docShellWin = do_QueryInterface(container);
+    nsIWidget* mainWidget = nsnull;
+    docShellWin->GetMainWidget(&mainWidget);
+    mainWidget->IsTouchWindow(aEnabled);
+  }*/
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHTMLDocument::SetMultitouchData(PRBool aEnable)
+{
+
+  nsPIDOMWindow *window = GetWindow();
+  if (!window)
+    return NS_ERROR_FAILURE;
+
+  nsIDocShell *docshell = window->GetDocShell();
+  if (!docshell)
+    return NS_ERROR_FAILURE;
+
+  nsPresContext *prescontext;
+  
+  docshell->GetPresContext(&prescontext);
+
+  if (!prescontext)
+    return NS_OK;
+
+  nsCOMPtr<nsISupports> container = prescontext->GetContainer();
+  if (!container)
+    return NS_OK;
+
+
+	nsCOMPtr<nsIBaseWindow> docShellWin = do_QueryInterface(container);
+	nsIWidget* mainWidget = nsnull;
+	docShellWin->GetMainWidget(&mainWidget);
+	if (aEnable) {
+	  mainWidget->RegisterTouchWindow();
+	  if (mainWidget->GetFirstChild()) mainWidget->GetFirstChild()->RegisterTouchWindow();
+	} else {
+	  mainWidget->UnregisterTouchWindow();
+	  if (mainWidget->GetFirstChild()) mainWidget->GetFirstChild()->UnregisterTouchWindow();
+	}
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsHTMLDocument::GetVlinkColor(nsAString& aVlinkColor)
 {
   aVlinkColor.Truncate();
 
   nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyContent());
   if (body) {
     body->GetVLink(aVlinkColor);
   }
diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -459,16 +459,18 @@
 #include "nsIDOMFileException.h"
 #include "nsIDOMFileError.h"
 
 // Simple gestures include
 #include "nsIDOMSimpleGestureEvent.h"
 
 #include "nsIDOMNSMouseEvent.h"
 
+#include "nsIDOMMozTouchEvent.h"
+
 #include "nsIEventListenerService.h"
 
 static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 
 static const char kDOMStringBundleURL[] =
   "chrome://global/locale/dom/dom.properties";
 
 // NOTE: DEFAULT_SCRIPTABLE_FLAGS and DOM_DEFAULT_SCRIPTABLE_FLAGS
@@ -1332,16 +1334,19 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(ScrollAreaEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(PopStateEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(EventListenerInfo, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(TransitionEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(MozTouchEvent, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
+
 };
 
 // Objects that should be constructable through |new Name();|
 struct nsContractIDMapData
 {
   PRInt32 mDOMClassInfoID;
   const char *mContractID;
 };
@@ -3743,16 +3748,23 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIEventListenerInfo)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(TransitionEvent, nsIDOMTransitionEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMTransitionEvent)
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
+  DOM_CLASSINFO_MAP_BEGIN(MozTouchEvent, nsIDOMMozTouchEvent)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozTouchEvent)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMMouseEvent)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSMouseEvent)
+    DOM_CLASSINFO_UI_EVENT_MAP_ENTRIES
+  DOM_CLASSINFO_MAP_END
+
 #ifdef NS_DEBUG
   {
     PRUint32 i = NS_ARRAY_LENGTH(sClassInfoData);
 
     if (i != eDOMClassInfoIDCount) {
       NS_ERROR("The number of items in sClassInfoData doesn't match the "
                "number of nsIDOMClassInfo ID's, this is bad! Fix it!");
 
diff --git a/dom/base/nsDOMClassInfoID.h b/dom/base/nsDOMClassInfoID.h
--- a/dom/base/nsDOMClassInfoID.h
+++ b/dom/base/nsDOMClassInfoID.h
@@ -474,16 +474,18 @@ enum nsDOMClassInfoID {
 
   eDOMClassInfo_ScrollAreaEvent_id,
   eDOMClassInfo_PopStateEvent_id,
 
   eDOMClassInfo_EventListenerInfo_id,
 
   eDOMClassInfo_TransitionEvent_id,
 
+  eDOMClassInfo_MozTouchEvent_id,
+
   // This one better be the last one in this list
   eDOMClassInfoIDCount
 };
 
 /**
  * nsIClassInfo helper macros
  */
 
diff --git a/dom/interfaces/events/Makefile.in b/dom/interfaces/events/Makefile.in
--- a/dom/interfaces/events/Makefile.in
+++ b/dom/interfaces/events/Makefile.in
@@ -75,15 +75,16 @@ XPIDLSRCS =					\
 	nsIDOMPageTransitionEvent.idl		\
 	nsIDOMCommandEvent.idl			\
 	nsIDOMMessageEvent.idl			\
 	nsIDOMNotifyPaintEvent.idl              \
 	nsIDOMPaintRequest.idl			\
 	nsIDOMPaintRequestList.idl		\
 	nsIDOMSimpleGestureEvent.idl		\
 	nsIDOMNSMouseEvent.idl			\
+	nsIDOMMozTouchEvent.idl			\
 	nsIDOMOrientationEvent.idl              \
 	nsIDOMScrollAreaEvent.idl		\
 	nsIDOMTransitionEvent.idl		\
 	nsIDOMPopStateEvent.idl			\
 	$(NULL)
 
 include $(topsrcdir)/config/rules.mk
diff --git a/dom/interfaces/html/nsIDOMNSHTMLDocument.idl b/dom/interfaces/html/nsIDOMNSHTMLDocument.idl
--- a/dom/interfaces/html/nsIDOMNSHTMLDocument.idl
+++ b/dom/interfaces/html/nsIDOMNSHTMLDocument.idl
@@ -45,16 +45,17 @@ interface nsIDOMNSHTMLDocument : nsISupp
   readonly attribute long                 width;
   readonly attribute long                 height;
            attribute DOMString            alinkColor;
            attribute DOMString            linkColor;
            attribute DOMString            vlinkColor;
            attribute DOMString            bgColor;
            attribute DOMString            fgColor;
            attribute DOMString            domain;
+           attribute boolean              multitouchData;
 
   readonly attribute nsIDOMHTMLCollection embeds;
 
   DOMString                 getSelection();
 
   // This is the internal version of open(); note that the version
   // scriptable with JS is defined entirely in classinfo.
   // If aContentType is not something supported by nsHTMLDocument and
diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -729,16 +729,17 @@ nsLayoutUtils::GetDOMEventCoordinatesRel
 nsPoint
 nsLayoutUtils::GetEventCoordinatesRelativeTo(const nsEvent* aEvent, nsIFrame* aFrame)
 {
   if (!aEvent || (aEvent->eventStructType != NS_MOUSE_EVENT && 
                   aEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
                   aEvent->eventStructType != NS_DRAG_EVENT &&
                   aEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT &&
                   aEvent->eventStructType != NS_GESTURENOTIFY_EVENT &&
+                  aEvent->eventStructType != NS_MOZTOUCH_EVENT &&
                   aEvent->eventStructType != NS_QUERY_CONTENT_EVENT))
     return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
 
   const nsGUIEvent* GUIEvent = static_cast<const nsGUIEvent*>(aEvent);
   if (!GUIEvent->widget)
     return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
 
   /* If we walk up the frame tree and discover that any of the frames are
diff --git a/widget/public/nsEvent.h b/widget/public/nsEvent.h
--- a/widget/public/nsEvent.h
+++ b/widget/public/nsEvent.h
@@ -83,13 +83,14 @@ class nsAccessibleEvent;
 class nsKeyEvent;
 class nsTextEvent;
 class nsCompositionEvent;
 class nsMouseScrollEvent;
 class nsReconversionEvent;
 class nsTooltipEvent;
 class nsMenuEvent;
 class nsSimpleGestureEvent;
+class nsMozTouchEvent;
 class nsContentCommandEvent;
 
 struct nsTextEventReply;
 
 #endif // nsEvent_h__
diff --git a/widget/public/nsGUIEvent.h b/widget/public/nsGUIEvent.h
--- a/widget/public/nsGUIEvent.h
+++ b/widget/public/nsGUIEvent.h
@@ -105,16 +105,17 @@ class nsHashKey;
 #define NS_MEDIA_EVENT                    34
 #endif // MOZ_MEDIA
 #define NS_DRAG_EVENT                     35
 #define NS_NOTIFYPAINT_EVENT              36
 #define NS_SIMPLE_GESTURE_EVENT           37
 #define NS_SELECTION_EVENT                38
 #define NS_CONTENT_COMMAND_EVENT          39
 #define NS_GESTURENOTIFY_EVENT            40
+#define NS_MOZTOUCH_EVENT                 41
 
 // 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
 // warned!
 #define NS_EVENT_FLAG_NONE                0x0000
 #define NS_EVENT_FLAG_TRUSTED             0x0001
 #define NS_EVENT_FLAG_BUBBLE              0x0002
 #define NS_EVENT_FLAG_CAPTURE             0x0004
@@ -449,16 +450,21 @@ class nsHashKey;
 #define NS_ORIENTATION_EVENT         4000
 
 #define NS_SCROLLAREA_EVENT_START    4100
 #define NS_SCROLLEDAREACHANGED       (NS_SCROLLAREA_EVENT_START)
 
 #define NS_TRANSITION_EVENT_START    4200
 #define NS_TRANSITION_END            (NS_TRANSITION_EVENT_START)
 
+#define NS_MOZTOUCH_EVENT_START  4300
+#define NS_MOZTOUCH_DOWN         (NS_MOZTOUCH_EVENT_START)
+#define NS_MOZTOUCH_MOVE         (NS_MOZTOUCH_EVENT_START+1)
+#define NS_MOZTOUCH_RELEASE      (NS_MOZTOUCH_EVENT_START+2)
+
 /**
  * Return status for event processors, nsEventStatus, is defined in
  * nsEvent.h.
  */
 
 /**
  * different types of (top-level) window z-level positioning
  */
@@ -1344,16 +1350,28 @@ public:
       propertyName(propertyNameArg), elapsedTime(elapsedTimeArg)
   {
   }
 
   nsString propertyName;
   float elapsedTime;
 };
 
+class nsMozTouchEvent : public nsMouseEvent_base
+{
+public:
+  nsMozTouchEvent(PRBool isTrusted, PRUint32 msg, nsIWidget* w,
+                  PRUint32 streamIdArg)
+    : nsMouseEvent_base(isTrusted, msg, w, NS_MOZTOUCH_EVENT),
+      streamId(streamIdArg)
+  {
+  }
+
+  PRUint32 streamId;
+};
 
 /**
  * Event status for D&D Event
  */
 enum nsDragDropEventStatus {  
   /// The event is a enter
   nsDragDropEventStatus_eDragEntered,            
   /// The event is exit
diff --git a/widget/public/nsIWidget.h b/widget/public/nsIWidget.h
--- a/widget/public/nsIWidget.h
+++ b/widget/public/nsIWidget.h
@@ -472,16 +472,19 @@ class nsIWidget : public nsISupports {
      * platforms.) This includes any title bar on the window.
      *
      *
      * @param aRect on return it holds the  x, y, width and height of this widget
      *
      */
     NS_IMETHOD GetScreenBounds(nsIntRect &aRect) = 0;
 
+    NS_IMETHOD RegisterTouchWindow() = 0;
+    NS_IMETHOD UnregisterTouchWindow() = 0;
+    NS_IMETHOD IsTouchWindow(PRBool* aIsTouchWindow) = 0;
 
     /**
      * Get this widget's client area dimensions, if the window has a 3D border appearance
      * this returns the area inside the border, The x and y are always zero
      *
      * @param aRect on return it holds the  x. y, width and height of the client area of this widget
      *
      */
diff --git a/widget/src/windows/nsWinGesture.cpp b/widget/src/windows/nsWinGesture.cpp
--- a/widget/src/windows/nsWinGesture.cpp
+++ b/widget/src/windows/nsWinGesture.cpp
@@ -58,16 +58,22 @@ HMODULE nsWinGesture::sLibraryHandle = n
 nsWinGesture::GetGestureInfoPtr nsWinGesture::getGestureInfo = nsnull;
 nsWinGesture::CloseGestureInfoHandlePtr nsWinGesture::closeGestureInfoHandle = nsnull;
 nsWinGesture::GetGestureExtraArgsPtr nsWinGesture::getGestureExtraArgs = nsnull;
 nsWinGesture::SetGestureConfigPtr nsWinGesture::setGestureConfig = nsnull;
 nsWinGesture::GetGestureConfigPtr nsWinGesture::getGestureConfig = nsnull;
 nsWinGesture::BeginPanningFeedbackPtr nsWinGesture::beginPanningFeedback = nsnull;
 nsWinGesture::EndPanningFeedbackPtr nsWinGesture::endPanningFeedback = nsnull;
 nsWinGesture::UpdatePanningFeedbackPtr nsWinGesture::updatePanningFeedback = nsnull;
+
+nsWinGesture::RegisterTouchWindowPtr nsWinGesture::registerTouchWindow = nsnull;
+nsWinGesture::UnregisterTouchWindowPtr nsWinGesture::unregisterTouchWindow = nsnull;
+nsWinGesture::GetTouchInputInfoPtr nsWinGesture::getTouchInputInfo = nsnull;
+nsWinGesture::CloseTouchInputHandlePtr nsWinGesture::closeTouchInputHandle = nsnull;
+
 static PRBool gEnableSingleFingerPanEvents = PR_FALSE;
 
 nsWinGesture::nsWinGesture() :
   mFeedbackActive(PR_FALSE),
   mXAxisFeedback(PR_FALSE),
   mYAxisFeedback(PR_FALSE),
   mPanActive(PR_FALSE),
   mPanInertiaActive(PR_FALSE)
@@ -94,27 +100,38 @@ PRBool nsWinGesture::InitLibrary()
 
   // gesture interfaces
   if (sLibraryHandle) {
     getGestureInfo = (GetGestureInfoPtr)GetProcAddress(sLibraryHandle, "GetGestureInfo");
     closeGestureInfoHandle = (CloseGestureInfoHandlePtr)GetProcAddress(sLibraryHandle, "CloseGestureInfoHandle");
     getGestureExtraArgs = (GetGestureExtraArgsPtr)GetProcAddress(sLibraryHandle, "GetGestureExtraArgs");
     setGestureConfig = (SetGestureConfigPtr)GetProcAddress(sLibraryHandle, "SetGestureConfig");
     getGestureConfig = (GetGestureConfigPtr)GetProcAddress(sLibraryHandle, "GetGestureConfig");
+    registerTouchWindow = (RegisterTouchWindowPtr)GetProcAddress(sLibraryHandle, "RegisterTouchWindow");
+    unregisterTouchWindow = (UnregisterTouchWindowPtr)GetProcAddress(sLibraryHandle, "UnregisterTouchWindow");
+    getTouchInputInfo = (GetTouchInputInfoPtr)GetProcAddress(sLibraryHandle, "GetTouchInputInfo");
+    closeTouchInputHandle = (CloseTouchInputHandlePtr)GetProcAddress(sLibraryHandle, "CloseTouchInputHandle");
   }
 
   if (!getGestureInfo || !closeGestureInfoHandle || !getGestureExtraArgs ||
     !setGestureConfig || !getGestureConfig) {
     getGestureInfo         = nsnull;
     closeGestureInfoHandle = nsnull;
     getGestureExtraArgs    = nsnull;
     setGestureConfig       = nsnull;
     getGestureConfig       = nsnull;
     return PR_FALSE;
   }
+  
+  if (!registerTouchWindow || !unregisterTouchWindow || !getTouchInputInfo || !closeTouchInputHandle) {
+    registerTouchWindow   = nsnull;
+    unregisterTouchWindow = nsnull;
+    getTouchInputInfo     = nsnull;
+    closeTouchInputHandle = nsnull;
+  }
 
   // panning feedback interfaces
   if (hTheme) {
     beginPanningFeedback = (BeginPanningFeedbackPtr)GetProcAddress(hTheme, "BeginPanningFeedback");
     endPanningFeedback = (EndPanningFeedbackPtr)GetProcAddress(hTheme, "EndPanningFeedback");
     updatePanningFeedback = (UpdatePanningFeedbackPtr)GetProcAddress(hTheme, "UpdatePanningFeedback");
   }
 
@@ -198,16 +215,48 @@ PRBool nsWinGesture::SetWinGestureSuppor
 
 /* Helpers */
 
 PRBool nsWinGesture::IsAvailable()
 {
   return getGestureInfo != nsnull;
 }
 
+PRBool nsWinGesture::RegisterTouchWindow(HWND hWnd)
+{
+  if (!registerTouchWindow)
+    return PR_FALSE;
+
+  return registerTouchWindow(hWnd, 0);
+}
+
+PRBool nsWinGesture::UnregisterTouchWindow(HWND hWnd)
+{
+  if (!unregisterTouchWindow)
+    return PR_FALSE;
+
+  return unregisterTouchWindow(hWnd);
+}
+
+PRBool nsWinGesture::GetTouchInputInfo(HTOUCHINPUT hTouchInput, PRUint32 cInputs, PTOUCHINPUT pInputs)
+{
+  if (!getTouchInputInfo)
+    return PR_FALSE;
+
+  return getTouchInputInfo(hTouchInput, cInputs, pInputs, sizeof(TOUCHINPUT));
+}
+
+PRBool nsWinGesture::CloseTouchInputHandle(HTOUCHINPUT hTouchInput)
+{
+  if (!closeTouchInputHandle)
+    return PR_FALSE;
+
+  return closeTouchInputHandle(hTouchInput);
+}
+
 PRBool nsWinGesture::GetGestureInfo(HGESTUREINFO hGestureInfo, PGESTUREINFO pGestureInfo)
 {
   if (!getGestureInfo || !hGestureInfo || !pGestureInfo)
     return PR_FALSE;
 
   ZeroMemory(pGestureInfo, sizeof(GESTUREINFO));
   pGestureInfo->cbSize = sizeof(GESTUREINFO);
 
@@ -233,16 +282,17 @@ PRBool nsWinGesture::GetGestureExtraArgs
 PRBool nsWinGesture::SetGestureConfig(HWND hWnd, UINT cIDs, PGESTURECONFIG pGestureConfig)
 {
   if (!getGestureInfo || !pGestureConfig)
     return PR_FALSE;
 
   return setGestureConfig(hWnd, 0, cIDs, pGestureConfig, sizeof(GESTURECONFIG));
 }
 
+
 PRBool nsWinGesture::GetGestureConfig(HWND hWnd, DWORD dwFlags, PUINT pcIDs, PGESTURECONFIG pGestureConfig)
 {
   if (!getGestureInfo || !pGestureConfig)
     return PR_FALSE;
 
   return getGestureConfig(hWnd, 0, dwFlags, pcIDs, pGestureConfig, sizeof(GESTURECONFIG));
 }
 
diff --git a/widget/src/windows/nsWinGesture.h b/widget/src/windows/nsWinGesture.h
--- a/widget/src/windows/nsWinGesture.h
+++ b/widget/src/windows/nsWinGesture.h
@@ -103,16 +103,33 @@ typedef GESTUREINFO const * PCGESTUREINF
 typedef struct tagGESTURENOTIFYSTRUCT {
     UINT cbSize;                    // size, in bytes, of this structure
     DWORD dwFlags;                  // unused
     HWND hwndTarget;                // handle to window targeted by the gesture
     POINTS ptsLocation;             // starting location
     DWORD dwInstanceID;             // internally used
 } GESTURENOTIFYSTRUCT, *PGESTURENOTIFYSTRUCT;
 
+/*
+ * Touch
+ */
+typedef struct _TOUCHINPUT {
+  LONG      x;
+  LONG      y;
+  HANDLE    hSource;
+  DWORD     dwID;
+  DWORD     dwFlags;
+  DWORD     dwMask;
+  DWORD     dwTime;
+  ULONG_PTR dwExtraInfo;
+  DWORD     cxContact;
+  DWORD     cyContact;
+}TOUCHINPUT, *PTOUCHINPUT;
+
+typedef HANDLE HTOUCHINPUT;
 
 /*
  * Gesture argument helpers
  *   - Angle should be a double in the range of -2pi to +2pi
  *   - Argument should be an unsigned 16-bit value
  */
 #define GID_ROTATE_ANGLE_TO_ARGUMENT(_arg_)     ((USHORT)((((_arg_) + 2.0 * 3.14159265) / (4.0 * 3.14159265)) * 65535.0))
 #define GID_ROTATE_ANGLE_FROM_ARGUMENT(_arg_)   ((((double)(_arg_) / 65535.0) * 4.0 * 3.14159265) - 2.0 * 3.14159265)
@@ -158,16 +175,35 @@ typedef struct tagGESTURENOTIFYSTRUCT {
 // Window events we need to respond to or receive
 #define WM_TABLET_QUERYSYSTEMGESTURESTATUS 0x02CC
 #define WM_GESTURE                         0x0119
 #define WM_GESTURENOTIFY                   0x011A
 
 // WM_TABLET_QUERYSYSTEMGESTURESTATUS return values
 #define TABLET_ROTATE_GESTURE_ENABLE    0x02000000
 
+// TOUCH
+#define WM_TOUCH 0x0240
+
+#define TOUCHEVENTF_MOVE       0x0001
+#define TOUCHEVENTF_DOWN       0x0002
+#define TOUCHEVENTF_UP         0x0004
+#define TOUCHEVENTF_INRANGE    0x0008
+#define TOUCHEVENTF_PRIMARY    0x0010
+#define TOUCHEVENTF_NOCOALESCE 0x0020
+#define TOUCHEVENTF_PEN        0x0040
+#define TOUCHEVENTF_PALM       0x0080
+
+#define TOUCHINPUTMASKF_TIMEFROMSYSTEM 0x0001
+#define TOUCHINPUTMASKF_EXTRAINFO      0x0002
+#define TOUCHINPUTMASKF_CONTACTAREA    0x0004
+
+#define TOUCH_COORD_TO_PIXEL(C) (C/100)
+
+
 #endif /* #ifndef HGESTUREINFO */
 
 class nsPointWin : public nsIntPoint
 {
 public:
    nsPointWin& operator=(const POINTS& aPoint) {
      x = aPoint.x; y = aPoint.y;
      return *this;
@@ -190,16 +226,20 @@ public:
 
 class nsWinGesture
 {
 public:
   nsWinGesture();
 
 public:
   PRBool SetWinGestureSupport(HWND hWnd, nsGestureNotifyEvent::ePanDirection aDirection);
+  PRBool RegisterTouchWindow(HWND hWnd);
+  PRBool UnregisterTouchWindow(HWND hWnd);
+  PRBool GetTouchInputInfo(HTOUCHINPUT hTouchInput, PRUint32 cInputs, PTOUCHINPUT pInputs);
+  PRBool CloseTouchInputHandle(HTOUCHINPUT hTouchInput);
   PRBool ShutdownWinGestureSupport();
   PRBool IsAvailable();
   
   // Simple gesture process
   PRBool ProcessGestureMessage(HWND hWnd, WPARAM wParam, LPARAM lParam, nsSimpleGestureEvent& evt);
 
   // Pan processing
   PRBool IsPanEvent(LPARAM lParam);
@@ -228,26 +268,34 @@ private:
   typedef BOOL (WINAPI * GetGestureInfoPtr)(HGESTUREINFO hGestureInfo, PGESTUREINFO pGestureInfo);
   typedef BOOL (WINAPI * CloseGestureInfoHandlePtr)(HGESTUREINFO hGestureInfo);
   typedef BOOL (WINAPI * GetGestureExtraArgsPtr)(HGESTUREINFO hGestureInfo, UINT cbExtraArgs, PBYTE pExtraArgs);
   typedef BOOL (WINAPI * SetGestureConfigPtr)(HWND hwnd, DWORD dwReserved, UINT cIDs, PGESTURECONFIG pGestureConfig, UINT cbSize);
   typedef BOOL (WINAPI * GetGestureConfigPtr)(HWND hwnd, DWORD dwReserved, DWORD dwFlags, PUINT pcIDs, PGESTURECONFIG pGestureConfig, UINT cbSize);
   typedef BOOL (WINAPI * BeginPanningFeedbackPtr)(HWND hWnd);
   typedef BOOL (WINAPI * EndPanningFeedbackPtr)(HWND hWnd, BOOL fAnimateBack);
   typedef BOOL (WINAPI * UpdatePanningFeedbackPtr)(HWND hWnd, LONG offsetX, LONG offsetY, BOOL fInInertia);
+  typedef BOOL (WINAPI * RegisterTouchWindowPtr)(HWND hWnd, ULONG flags);
+  typedef BOOL (WINAPI * UnregisterTouchWindowPtr)(HWND hWnd);
+  typedef BOOL (WINAPI * GetTouchInputInfoPtr)(HTOUCHINPUT hTouchInput, PRUint32 cInputs, PTOUCHINPUT pInputs, PRInt32 cbSize);
+  typedef BOOL (WINAPI * CloseTouchInputHandlePtr)(HTOUCHINPUT hTouchInput);
 
   // Static function pointers
   static GetGestureInfoPtr getGestureInfo;
   static CloseGestureInfoHandlePtr closeGestureInfoHandle;
   static GetGestureExtraArgsPtr getGestureExtraArgs;
   static SetGestureConfigPtr setGestureConfig;
   static GetGestureConfigPtr getGestureConfig;
   static BeginPanningFeedbackPtr beginPanningFeedback;
   static EndPanningFeedbackPtr endPanningFeedback;
   static UpdatePanningFeedbackPtr updatePanningFeedback;
+  static RegisterTouchWindowPtr registerTouchWindow;
+  static UnregisterTouchWindowPtr unregisterTouchWindow;
+  static GetTouchInputInfoPtr getTouchInputInfo;
+  static CloseTouchInputHandlePtr closeTouchInputHandle;
 
   // Delay load info 
   PRBool InitLibrary();
 
   static HMODULE sLibraryHandle;
   static const PRUnichar kGestureLibraryName[];
   static const PRUnichar kThemeLibraryName[];
 
diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -374,16 +374,17 @@ nsWindow::nsWindow() : nsBaseWidget()
   mPrevWndProc          = nsnull;
   mOldIMC               = nsnull;
   mNativeDragTarget     = nsnull;
   mInDtor               = PR_FALSE;
   mIsVisible            = PR_FALSE;
   mHas3DBorder          = PR_FALSE;
   mIsInMouseCapture     = PR_FALSE;
   mIsTopWidgetWindow    = PR_FALSE;
+  mTouchWindow          = PR_FALSE;
   mUnicodeWidget        = PR_TRUE;
   mWindowType           = eWindowType_child;
   mBorderStyle          = eBorderStyle_default;
   mPopupType            = ePopupTypeAny;
   mDisplayPanFeedback   = PR_FALSE;
   mLastPoint.x          = 0;
   mLastPoint.y          = 0;
   mLastSize.width       = 0;
@@ -1224,16 +1225,48 @@ void nsWindow::ClearThemeRegion()
 #ifndef WINCE
   if (nsUXThemeData::sIsVistaOrLater && mTransparencyMode != eTransparencyGlass &&
       mWindowType == eWindowType_popup && (mPopupType == ePopupTypeTooltip || mPopupType == ePopupTypePanel)) {
     SetWindowRgn(mWnd, NULL, false);
   }
 #endif
 }
 
+BOOL CALLBACK nsWindow::RealRegisterTouch(HWND aWnd, LPARAM aMsg) {
+  printf("@ %x\n", aWnd);
+  nsWindow* nsWin = GetNSWindowPtr(aWnd);
+  nsWin->mGesture.RegisterTouchWindow(aWnd);
+  return TRUE;
+}
+
+BOOL CALLBACK nsWindow::RealUnregisterTouch(HWND aWnd, LPARAM aMsg) {
+  printf("@ %x\n", aWnd);
+  nsWindow* nsWin = GetNSWindowPtr(aWnd);
+  (nsWin->mGesture).UnregisterTouchWindow(aWnd);
+  return TRUE;
+}
+NS_METHOD nsWindow::IsTouchWindow(PRBool *aIsTouchWindow) {
+  *aIsTouchWindow = mTouchWindow;
+  return NS_OK;
+}
+
+NS_METHOD nsWindow::RegisterTouchWindow() {
+  mTouchWindow = PR_TRUE;
+  printf("Registering touch for descendants of %x:\n", mWnd);
+  ::EnumChildWindows(mWnd, nsWindow::RealRegisterTouch, NULL);
+  return NS_OK;
+}
+
+NS_METHOD nsWindow::UnregisterTouchWindow() {
+  mTouchWindow = PR_FALSE;
+  printf("Unregistering touch for descendants of %x:\n", mWnd);
+  ::EnumChildWindows(mWnd, nsWindow::RealUnregisterTouch, NULL);
+  return NS_OK;
+}
+
 void nsWindow::SetThemeRegion()
 {
 #ifndef WINCE
   // Popup types that have a visual styles region applied (bug 376408). This can be expanded
   // for other window types as needed. The regions are applied generically to the base window
   // so default constants are used for part and state. At some point we might need part and
   // state values from nsNativeThemeWin's GetThemePartAndState, but currently windows that
   // change shape based on state haven't come up.
@@ -4474,17 +4507,22 @@ PRBool nsWindow::ProcessMessage(UINT msg
 
   /* Gesture support events */
   case WM_TABLET_QUERYSYSTEMGESTURESTATUS:
     // According to MS samples, this must be handled to enable
     // rotational support in multi-touch drivers.
     result = PR_TRUE;
     *aRetValue = TABLET_ROTATE_GESTURE_ENABLE;
     break;
-    
+
+  case WM_TOUCH:
+    result = OnTouch(wParam, lParam);
+    *aRetValue = result;
+    break;
+
   case WM_GESTURE:
     result = OnGesture(wParam, lParam);
     break;
 
   case WM_GESTURENOTIFY:
     {
       if (mWindowType != eWindowType_invisible &&
           mWindowType != eWindowType_plugin &&
@@ -4497,17 +4535,18 @@ PRBool nsWindow::ProcessMessage(UINT msg
         nsPointWin touchPoint;
         touchPoint = gestureinfo->ptsLocation;
         touchPoint.ScreenToClient(mWnd);
         nsGestureNotifyEvent gestureNotifyEvent(PR_TRUE, NS_GESTURENOTIFY_EVENT_START, this);
         gestureNotifyEvent.refPoint = touchPoint;
         nsEventStatus status;
         DispatchEvent(&gestureNotifyEvent, status);
         mDisplayPanFeedback = gestureNotifyEvent.displayPanFeedback;
-        mGesture.SetWinGestureSupport(mWnd, gestureNotifyEvent.panDirection);
+        if (!mTouchWindow)
+          mGesture.SetWinGestureSupport(mWnd, gestureNotifyEvent.panDirection);
       }
       result = PR_FALSE; //should always bubble to DefWindowProc
     }
     break;
 #endif // !defined(WINCE)
 
     case WM_CLEAR:
     {
@@ -5170,16 +5209,73 @@ void nsWindow::OnWindowPosChanging(LPWIN
     NS_IF_RELEASE(event.mActualBelow);
   }
   // prevent rude external programs from making hidden window visible
   if (mWindowType == eWindowType_invisible)
     info->flags &= ~SWP_SHOWWINDOW;
 }
 #endif
 
+PRBool nsWindow::OnTouch(WPARAM wParam, LPARAM lParam)
+{
+  //if (mContentType != eContentTypeContent) return PR_FALSE;
+  PRUint32 cInputs = LOWORD(wParam);
+  PTOUCHINPUT pInputs = new TOUCHINPUT[cInputs];
+  if (pInputs == nsnull)
+    return PR_FALSE;
+  
+  if (mGesture.GetTouchInputInfo((HTOUCHINPUT)lParam, cInputs, pInputs)) {
+    for (PRUint32 i=0; i < cInputs; i++) {
+
+      int MSG = 0;
+      if (pInputs[i].dwFlags & TOUCHEVENTF_MOVE) {
+        MSG = NS_MOZTOUCH_MOVE;
+      } else if (pInputs[i].dwFlags & TOUCHEVENTF_DOWN) {
+        MSG = NS_MOZTOUCH_DOWN;
+      } else if (pInputs[i].dwFlags & TOUCHEVENTF_UP) {
+        MSG = NS_MOZTOUCH_RELEASE;
+      }
+
+      if (!MSG)
+        continue;
+
+      nsPointWin touchPoint;
+      touchPoint.x = TOUCH_COORD_TO_PIXEL(pInputs[i].x);
+      touchPoint.y = TOUCH_COORD_TO_PIXEL(pInputs[i].y);
+      touchPoint.ScreenToClient(mWnd);
+      
+      nsMozTouchEvent touchEvent(PR_TRUE, MSG, this, 0);
+      touchEvent.refPoint = touchPoint;
+      touchEvent.streamId = pInputs[i].dwID;
+
+      nsEventStatus status;
+      DispatchEvent(&touchEvent, status);
+
+//      printf("Touch info: %d %d %d\n", pInputs[i].dwID,
+//                                       TOUCH_COORD_TO_PIXEL(pInputs[i].x),
+//                                       TOUCH_COORD_TO_PIXEL(pInputs[i].y));
+
+    }
+//    putchar('\n');
+  }
+  else
+  {
+      // GetLastError() and error handling
+  }
+
+  delete [] pInputs;
+
+  if (!mGesture.CloseTouchInputHandle((HTOUCHINPUT)lParam))
+  {
+    // error handling*/
+  }
+  return PR_FALSE;
+}
+
+
 // Gesture event processing. Handles WM_GESTURE events.
 #if !defined(WINCE)
 PRBool nsWindow::OnGesture(WPARAM wParam, LPARAM lParam)
 {
   // Treatment for pan events which translate into scroll events:
   if (mGesture.IsPanEvent(lParam)) {
     nsMouseScrollEvent event(PR_TRUE, NS_MOUSE_PIXEL_SCROLL, this);
 
diff --git a/widget/src/windows/nsWindow.h b/widget/src/windows/nsWindow.h
--- a/widget/src/windows/nsWindow.h
+++ b/widget/src/windows/nsWindow.h
@@ -171,16 +171,20 @@ public:
                                                      PRUint32 aModifierFlags);
   NS_IMETHOD              ResetInputState();
   NS_IMETHOD              SetIMEOpenState(PRBool aState);
   NS_IMETHOD              GetIMEOpenState(PRBool* aState);
   NS_IMETHOD              SetIMEEnabled(PRUint32 aState);
   NS_IMETHOD              GetIMEEnabled(PRUint32* aState);
   NS_IMETHOD              CancelIMEComposition();
   NS_IMETHOD              GetToggledKeyState(PRUint32 aKeyCode, PRBool* aLEDState);
+  
+  NS_IMETHOD            RegisterTouchWindow();
+  NS_IMETHOD            UnregisterTouchWindow();
+  NS_IMETHOD            IsTouchWindow(PRBool *aIsTouchWindow);
 #ifdef MOZ_XUL
   virtual void            SetTransparencyMode(nsTransparencyMode aMode);
   virtual nsTransparencyMode GetTransparencyMode();
 #endif // MOZ_XUL
 #ifdef NS_ENABLE_TSF
   NS_IMETHOD              OnIMEFocusChange(PRBool aFocus);
   NS_IMETHOD              OnIMETextChange(PRUint32 aStart, PRUint32 aOldEnd, PRUint32 aNewEnd);
   NS_IMETHOD              OnIMESelectionChange(void);
@@ -253,16 +257,18 @@ protected:
 
   /**
    * Callbacks
    */
   static LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
   static BOOL CALLBACK    BroadcastMsgToChildren(HWND aWnd, LPARAM aMsg);
   static BOOL CALLBACK    BroadcastMsg(HWND aTopWindow, LPARAM aMsg);
   static BOOL CALLBACK    DispatchStarvedPaints(HWND aTopWindow, LPARAM aMsg);
+  static BOOL CALLBACK    RealRegisterTouch(HWND aTopWindow, LPARAM aMsg);
+  static BOOL CALLBACK    RealUnregisterTouch(HWND aTopWindow, LPARAM aMsg);
   static LRESULT CALLBACK MozSpecialMsgFilter(int code, WPARAM wParam, LPARAM lParam);
   static LRESULT CALLBACK MozSpecialWndProc(int code, WPARAM wParam, LPARAM lParam);
   static LRESULT CALLBACK MozSpecialMouseProc(int code, WPARAM wParam, LPARAM lParam);
   static VOID    CALLBACK HookTimerForPopups( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime );
 
   /**
    * Window utilities
    */
@@ -329,16 +335,17 @@ protected:
   LRESULT                 OnCharRaw(UINT charCode, UINT aScanCode,
                                     nsModifierKeyState &aModKeyState,
                                     PRUint32 aFlags = 0,
                                     const MSG *aMsg = nsnull,
                                     PRBool *aEventDispatched = nsnull);
   virtual PRBool          OnScroll(UINT aMsg, WPARAM aWParam, LPARAM aLParam);
   virtual HBRUSH          OnControlColor();
   PRBool                  OnGesture(WPARAM wParam, LPARAM lParam);
+  PRBool                  OnTouch(WPARAM wParam, LPARAM lParam);
   PRBool                  OnHotKey(WPARAM wParam, LPARAM lParam);
   BOOL                    OnInputLangChange(HKL aHKL);
   void                    OnSettingsChange(WPARAM wParam, LPARAM lParam);
   virtual PRBool          OnPaint(HDC aDC = nsnull);
   void                    OnWindowPosChanged(WINDOWPOS *wp, PRBool& aResult);
 #if defined(CAIRO_HAS_DDRAW_SURFACE)
   PRBool                  OnPaintImageDDraw16();
 #endif // defined(CAIRO_HAS_DDRAW_SURFACE)
@@ -411,16 +418,17 @@ protected:
   HBRUSH                mBrush;
   PRPackedBool          mIsTopWidgetWindow;
   PRPackedBool          mHas3DBorder;
   PRPackedBool          mInDtor;
   PRPackedBool          mIsVisible;
   PRPackedBool          mIsInMouseCapture;
   PRPackedBool          mUnicodeWidget;
   PRPackedBool          mPainting;
+  PRPackedBool          mTouchWindow;
   char                  mLeadByte;
   PRUint32              mBlurSuppressLevel;
   nsContentType         mContentType;
   PRInt32               mMenuCmdId;
   DWORD_PTR             mOldStyle;
   DWORD_PTR             mOldExStyle;
   HIMC                  mOldIMC;
   PRUint32              mIMEEnabled;
diff --git a/widget/src/xpwidgets/nsBaseWidget.cpp b/widget/src/xpwidgets/nsBaseWidget.cpp
--- a/widget/src/xpwidgets/nsBaseWidget.cpp
+++ b/widget/src/xpwidgets/nsBaseWidget.cpp
@@ -740,16 +740,33 @@ NS_METHOD nsBaseWidget::GetBounds(nsIntR
 * this method must be overridden
 *
 **/
 NS_METHOD nsBaseWidget::GetScreenBounds(nsIntRect &aRect)
 {
   return GetBounds(aRect);
 }
 
+NS_METHOD nsBaseWidget::RegisterTouchWindow()
+{
+  printf("Register touch window on nsBaseWidget\n");
+  return NS_OK;
+}
+
+NS_METHOD nsBaseWidget::UnregisterTouchWindow()
+{
+  printf("Unregister touch window on nsBaseWidget\n");
+  return NS_OK;
+}
+
+NS_METHOD nsBaseWidget::IsTouchWindow(PRBool* aIsTouchWindow)
+{
+  *aIsTouchWindow = PR_FALSE;
+  return NS_OK;
+}
 /**
 * 
 *
 **/
 NS_METHOD nsBaseWidget::SetBounds(const nsIntRect &aRect)
 {
   mBounds = aRect;
 
diff --git a/widget/src/xpwidgets/nsBaseWidget.h b/widget/src/xpwidgets/nsBaseWidget.h
--- a/widget/src/xpwidgets/nsBaseWidget.h
+++ b/widget/src/xpwidgets/nsBaseWidget.h
@@ -110,16 +110,19 @@ public:
   virtual nsIToolkit*     GetToolkit();  
   virtual gfxASurface*    GetThebesSurface();
   NS_IMETHOD              SetModal(PRBool aModal); 
   NS_IMETHOD              SetWindowClass(const nsAString& xulWinType);
   NS_IMETHOD              SetBounds(const nsIntRect &aRect);
   NS_IMETHOD              GetBounds(nsIntRect &aRect);
   NS_IMETHOD              GetClientBounds(nsIntRect &aRect);
   NS_IMETHOD              GetScreenBounds(nsIntRect &aRect);
+  NS_IMETHOD              RegisterTouchWindow();
+  NS_IMETHOD              UnregisterTouchWindow();
+  NS_IMETHOD              IsTouchWindow(PRBool *aIsTouchWindow);
   NS_IMETHOD              EnableDragDrop(PRBool aEnable);
   NS_IMETHOD              GetAttention(PRInt32 aCycleCount);
   virtual PRBool          HasPendingInputEvent();
   NS_IMETHOD              SetIcon(const nsAString &anIconSpec);
   NS_IMETHOD              BeginSecureKeyboardInput();
   NS_IMETHOD              EndSecureKeyboardInput();
   NS_IMETHOD              SetWindowTitlebarColor(nscolor aColor, PRBool aActive);
   virtual void            SetDrawsInTitlebar(PRBool aState) {}
