Index: nsImageDocument.cpp
===================================================================
RCS file: /cvsroot/mozilla/content/html/document/src/nsImageDocument.cpp,v
retrieving revision 1.138.4.5
diff -u -r1.138.4.5 nsImageDocument.cpp
--- nsImageDocument.cpp	11 Aug 2006 18:22:02 -0000	1.138.4.5
+++ nsImageDocument.cpp	6 Feb 2008 14:10:10 -0000
@@ -135,6 +135,9 @@
   PRInt32                       mImageWidth;
   PRInt32                       mImageHeight;
 
+  PRInt32                       mMovingOriginX;
+  PRInt32                       mMovingOriginY;
+
   PRPackedBool                  mResizeImageByDefault;
   PRPackedBool                  mImageIsOverflowing;
   // mImageIsResized is true if the image is currently resized
@@ -144,6 +147,8 @@
   // can be false when this is true
   PRPackedBool                  mShouldResize;
   PRPackedBool                  mFirstResize;
+  PRPackedBool                  mStartedMoving;
+  PRPackedBool                  mMoving;
 };
 
 NS_IMPL_ADDREF_INHERITED(ImageListener, nsMediaDocumentStreamListener)
@@ -313,6 +318,10 @@
     // Remove our event listener from the image content.
     nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mImageContent);
     target->RemoveEventListener(NS_LITERAL_STRING("click"), this, PR_FALSE);
+    target->RemoveEventListener(NS_LITERAL_STRING("draggesture"), this, PR_FALSE);
+    target->RemoveEventListener(NS_LITERAL_STRING("mousedown"), this, PR_FALSE);
+    target->RemoveEventListener(NS_LITERAL_STRING("mouseup"), this, PR_FALSE);
+    target->RemoveEventListener(NS_LITERAL_STRING("mousemove"), this, PR_FALSE);
 
     // Break reference cycle with mImageContent, if we have one
     nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mImageContent);
@@ -352,6 +361,10 @@
 
       target = do_QueryInterface(mImageContent);
       target->AddEventListener(NS_LITERAL_STRING("click"), this, PR_FALSE);
+      target->AddEventListener(NS_LITERAL_STRING("draggesture"), this, PR_FALSE);
+      target->AddEventListener(NS_LITERAL_STRING("mousedown"), this, PR_FALSE);
+      target->AddEventListener(NS_LITERAL_STRING("mouseup"), this, PR_FALSE);
+      target->AddEventListener(NS_LITERAL_STRING("mousemove"), this, PR_TRUE);
     }
 
     target = do_QueryInterface(aScriptGlobalObject);
@@ -436,6 +449,7 @@
   if (!view)
     return NS_OK;
 
+
   nsSize scrolledSize;
   if (NS_FAILED(view->GetContainerSize(&scrolledSize.width, &scrolledSize.height)))
     return NS_OK;
@@ -553,25 +567,106 @@
     CheckOverflowing(PR_FALSE);
   }
   else if (eventType.EqualsLiteral("click")) {
-    mShouldResize = PR_TRUE;
-    if (mImageIsResized) {
-      PRInt32 x = 0, y = 0;
+    if (mMoving)
+      mMoving = PR_FALSE;
+    else {
+      mStartedMoving = PR_FALSE;
+      mMoving = PR_FALSE;
+      mShouldResize = PR_TRUE;
+      if (mImageIsResized) {
+        PRInt32 x = 0, y = 0;
+        nsCOMPtr<nsIDOMMouseEvent> event(do_QueryInterface(aEvent));
+        if (event) {
+          event->GetClientX(&x);
+          event->GetClientY(&y);
+          PRInt32 left = 0, top = 0;
+          nsCOMPtr<nsIDOMNSHTMLElement> nsElement(do_QueryInterface(mImageContent));
+          nsElement->GetOffsetLeft(&left);
+          nsElement->GetOffsetTop(&top);
+          x -= left;
+          y -= top;
+        }
+        mShouldResize = PR_FALSE;
+        RestoreImageTo(x, y);
+      }
+      else if (mImageIsOverflowing) {
+        ShrinkToFit();
+      }
+    }
+  }
+  else if (eventType.EqualsLiteral("draggesture")) {
+    PRBool isShiftKeyPressed;
+    nsCOMPtr<nsIDOMMouseEvent> event(do_QueryInterface(aEvent));
+    if (event &&
+        NS_SUCCEEDED(event->GetShiftKey(&isShiftKeyPressed)) &&
+        isShiftKeyPressed)
+      aEvent->PreventDefault();
+  }
+  else if (eventType.EqualsLiteral("mousedown")) {
+    if (!mImageIsResized) {
+      PRBool isShiftKeyPressed;
       nsCOMPtr<nsIDOMMouseEvent> event(do_QueryInterface(aEvent));
-      if (event) {
-        event->GetClientX(&x);
-        event->GetClientY(&y);
-        PRInt32 left = 0, top = 0;
-        nsCOMPtr<nsIDOMNSHTMLElement> nsElement(do_QueryInterface(mImageContent));
-        nsElement->GetOffsetLeft(&left);
-        nsElement->GetOffsetTop(&top);
-        x -= left;
-        y -= top;
+      if (event &&
+          NS_SUCCEEDED(event->GetShiftKey(&isShiftKeyPressed)) &&
+          isShiftKeyPressed) {
+        mStartedMoving = PR_TRUE;
+        mMoving = PR_FALSE;
+        nsCOMPtr<nsIDOMMouseEvent> event(do_QueryInterface(aEvent));
+        if (event) {
+          event->GetScreenX(&mMovingOriginX);
+          event->GetScreenY(&mMovingOriginY);
+        }
       }
-      mShouldResize = PR_FALSE;
-      RestoreImageTo(x, y);
     }
-    else if (mImageIsOverflowing) {
-      ShrinkToFit();
+  }
+  else if (eventType.EqualsLiteral("mousemove") &&
+           mStartedMoving) {
+    nsCOMPtr<nsIDOMMouseEvent> event(do_QueryInterface(aEvent));
+    if (event) {
+      PRInt32 x, y;
+      event->GetScreenX(&x);
+      event->GetScreenY(&y);
+
+      nsIPresShell *shell = GetShellAt(0);
+      if (!shell)
+        return NS_OK;
+
+      nsPresContext* context = shell->GetPresContext();
+      if (!context)
+        return NS_OK;
+
+      nsIViewManager* vm = context->GetViewManager();
+      if (!vm)
+        return NS_OK;
+
+      nsIScrollableView* view;
+      vm->GetRootScrollableView(&view);
+      if (!view)
+        return NS_OK;
+
+      nscoord xPos, yPos;
+      if (NS_FAILED(view->GetScrollPosition(xPos, yPos)))
+        return NS_OK;
+
+      view->ScrollTo(xPos - NSToCoordRound((mMovingOriginX - x)*context->PixelsToTwips()),
+                     yPos - NSToCoordRound((mMovingOriginY - y)*context->PixelsToTwips()),
+                     NS_VMREFRESH_IMMEDIATE);
+
+      mImageContent->SetAttr(kNameSpaceID_None, nsHTMLAtoms::style,
+                             NS_LITERAL_STRING("cursor: move"), PR_TRUE);
+      mMoving = PR_TRUE;
+    }
+  }
+  else if (eventType.EqualsLiteral("mouseup") &&
+           mMoving) {
+    mStartedMoving = PR_FALSE;
+    nsCOMPtr<nsIDOMMouseEvent> event(do_QueryInterface(aEvent));
+    if (event) {
+      PRInt32 x, y;
+      event->GetScreenX(&x);
+      event->GetScreenY(&y);
+      mImageContent->SetAttr(kNameSpaceID_None, nsHTMLAtoms::style,
+                             NS_LITERAL_STRING("cursor: -moz-zoom-out"), PR_TRUE);
     }
   }
   else if (eventType.EqualsLiteral("keypress")) {
