Bug 773741 - Support touch events in resizers. r=enn
authorWes Johnston <wjohnston@mozilla.com>
Fri, 27 Jul 2012 15:01:12 -0700
changeset 100779 853e5839a8afd76ba0ed8b0ea9c0b3f3ff28e6c8
parent 100778 64d7f92c3029ac265828302cd0b97a94e509349c
child 100780 377f1998ca05ff2fa91381b8791a38e58462f0da
push id23193
push userryanvm@gmail.com
push dateSat, 28 Jul 2012 21:54:39 +0000
treeherdermozilla-central@29bff59d3bbe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersenn
bugs773741
milestone17.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 773741 - Support touch events in resizers. r=enn
layout/xul/base/src/nsBoxFrame.cpp
layout/xul/base/src/nsBoxFrame.h
layout/xul/base/src/nsResizerFrame.cpp
layout/xul/base/src/nsResizerFrame.h
layout/xul/base/src/nsSliderFrame.cpp
layout/xul/base/src/nsSliderFrame.h
layout/xul/base/test/Makefile.in
--- a/layout/xul/base/src/nsBoxFrame.cpp
+++ b/layout/xul/base/src/nsBoxFrame.cpp
@@ -28,16 +28,17 @@
 // ----------------------------
 // Boxes layout out top down by adding up their children's min, max, and preferred sizes. Only problem is if a incremental
 // reflow occurs. The preferred size of a child deep in the hierarchy could change. And this could change
 // any number of syblings around the box. Basically any children in the reflow chain must have their caches cleared
 // so when asked for there current size they can relayout themselves. 
 
 #include "nsBoxLayoutState.h"
 #include "nsBoxFrame.h"
+#include "nsDOMTouchEvent.h"
 #include "nsStyleContext.h"
 #include "nsPresContext.h"
 #include "nsCOMPtr.h"
 #include "nsINameSpaceManager.h"
 #include "nsGkAtoms.h"
 #include "nsIContent.h"
 #include "nsHTMLParts.h"
 #include "nsIViewManager.h"
@@ -2168,8 +2169,40 @@ private:
 nsresult
 nsBoxFrame::WrapListsInRedirector(nsDisplayListBuilder*   aBuilder,
                                   const nsDisplayListSet& aIn,
                                   const nsDisplayListSet& aOut)
 {
   nsXULEventRedirectorWrapper wrapper(this);
   return wrapper.WrapLists(aBuilder, this, aIn, aOut);
 }
+
+bool
+nsBoxFrame::GetEventPoint(nsGUIEvent* aEvent, nsPoint &aPoint) {
+  nsIntPoint refPoint;
+  bool res = GetEventPoint(aEvent, refPoint);
+  aPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, refPoint, this);
+  return res;
+}
+
+bool
+nsBoxFrame::GetEventPoint(nsGUIEvent* aEvent, nsIntPoint &aPoint) {
+  NS_ENSURE_TRUE(aEvent, false);
+
+  if (aEvent->eventStructType == NS_TOUCH_EVENT) {
+    nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
+    // return false if there is more than one touch on the page, or if
+    // we can't find a touch point
+    if (touchEvent->touches.Length() != 1) {
+      return false;
+    }
+  
+    nsIDOMTouch *touch = touchEvent->touches.SafeElementAt(0);
+    if (!touch) {
+      return false;
+    }
+    nsDOMTouch* domtouch = static_cast<nsDOMTouch*>(touch);
+    aPoint = domtouch->mRefPoint;
+  } else {
+    aPoint = aEvent->refPoint;
+  }
+  return true;
+}
--- a/layout/xul/base/src/nsBoxFrame.h
+++ b/layout/xul/base/src/nsBoxFrame.h
@@ -205,16 +205,23 @@ protected:
     nsSize mPrefSize;
     nsSize mMinSize;
     nsSize mMaxSize;
     nscoord mFlex;
     nscoord mAscent;
 
     nsCOMPtr<nsBoxLayout> mLayoutManager;
 
+    // Get the point associated with this event. Returns true if a single valid
+    // point was found. Otherwise false.
+    bool GetEventPoint(nsGUIEvent *aEvent, nsPoint &aPoint);
+    // Gets the event coordinates relative to the widget offset associated with
+    // this frame. Return true if a single valid point was found.
+    bool GetEventPoint(nsGUIEvent *aEvent, nsIntPoint &aPoint);
+
 protected:
     nsresult RegUnregAccessKey(bool aDoReg);
 
   NS_HIDDEN_(void) CheckBoxOrder(nsBoxLayoutState& aState);
 
 private: 
 
 #ifdef DEBUG_LAYOUT
--- a/layout/xul/base/src/nsResizerFrame.cpp
+++ b/layout/xul/base/src/nsResizerFrame.cpp
@@ -57,19 +57,21 @@ nsResizerFrame::HandleEvent(nsPresContex
   if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
     return NS_OK;
   }
 
   nsWeakFrame weakFrame(this);
   bool doDefault = true;
 
   switch (aEvent->message) {
+    case NS_TOUCH_START:
     case NS_MOUSE_BUTTON_DOWN: {
-      if (aEvent->eventStructType == NS_MOUSE_EVENT &&
-        static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton)
+      if (aEvent->eventStructType == NS_TOUCH_EVENT ||
+          (aEvent->eventStructType == NS_MOUSE_EVENT &&
+        static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton))
       {
         nsCOMPtr<nsIBaseWindow> window;
         nsIPresShell* presShell = aPresContext->GetPresShell();
         nsIContent* contentToResize =
           GetContentToResize(presShell, getter_AddRefs(window));
         if (contentToResize) {
           nsIFrame* frameToResize = contentToResize->GetPrimaryFrame();
           if (!frameToResize)
@@ -107,42 +109,48 @@ nsResizerFrame::HandleEvent(nsPresContex
              break;
              
           // if there's no native resize support, we need to do window
           // resizing ourselves
           window->GetPositionAndSize(&mMouseDownRect.x, &mMouseDownRect.y,
                                      &mMouseDownRect.width, &mMouseDownRect.height);
         }
 
+        // remember current mouse coordinates
+        nsIntPoint refPoint;
+        if (!GetEventPoint(aEvent, refPoint))
+          return NS_OK;
+        mMouseDownPoint = refPoint + aEvent->widget->WidgetToScreenOffset();
+
         // we're tracking
         mTrackingMouseMove = true;
 
-        // remember current mouse coordinates
-        mMouseDownPoint = aEvent->refPoint + aEvent->widget->WidgetToScreenOffset();
-
         nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
       }
     }
     break;
 
+  case NS_TOUCH_END:
   case NS_MOUSE_BUTTON_UP: {
 
-    if (mTrackingMouseMove && aEvent->eventStructType == NS_MOUSE_EVENT &&
-        static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton)
+      if (aEvent->eventStructType == NS_TOUCH_EVENT ||
+          (aEvent->eventStructType == NS_MOUSE_EVENT &&
+        static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton))
     {
       // we're done tracking.
       mTrackingMouseMove = false;
 
       nsIPresShell::SetCapturingContent(nsnull, 0);
 
       doDefault = false;
     }
   }
   break;
 
+  case NS_TOUCH_MOVE:
   case NS_MOUSE_MOVE: {
     if (mTrackingMouseMove)
     {
       nsCOMPtr<nsIBaseWindow> window;
       nsIPresShell* presShell = aPresContext->GetPresShell();
       nsCOMPtr<nsIContent> contentToResize =
         GetContentToResize(presShell, getter_AddRefs(window));
 
@@ -155,17 +163,20 @@ nsResizerFrame::HandleEvent(nsPresContex
         }
       }
 
       // both MouseMove and direction are negative when pointing to the
       // top and left, and positive when pointing to the bottom and right
 
       // retrieve the offset of the mousemove event relative to the mousedown.
       // The difference is how much the resize needs to be
-      nsIntPoint screenPoint(aEvent->refPoint + aEvent->widget->WidgetToScreenOffset());
+      nsIntPoint refPoint;
+      if (!GetEventPoint(aEvent, refPoint))
+        return NS_OK;
+      nsIntPoint screenPoint(refPoint + aEvent->widget->WidgetToScreenOffset());
       nsIntPoint mouseMove(screenPoint - mMouseDownPoint);
 
       // Determine which direction to resize by checking the dir attribute.
       // For windows and menus, ensure that it can be resized in that direction.
       Direction direction = GetDirection();
       if (window || menuPopupFrame) {
         if (menuPopupFrame) {
           menuPopupFrame->CanAdjustEdges(
--- a/layout/xul/base/src/nsResizerFrame.h
+++ b/layout/xul/base/src/nsResizerFrame.h
@@ -42,14 +42,15 @@ protected:
     nsString width, height;
   };
   static void SizeInfoDtorFunc(void *aObject, nsIAtom *aPropertyName,
                                void *aPropertyValue, void *aData);
   static void ResizeContent(nsIContent* aContent, const Direction& aDirection,
                             const SizeInfo& aSizeInfo, SizeInfo* aOriginalSizeInfo);
   static void MaybePersistOriginalSize(nsIContent* aContent, const SizeInfo& aSizeInfo);
   static void RestoreOriginalSize(nsIContent* aContent);
+
 protected:
 	nsIntRect mMouseDownRect;
 	nsIntPoint mMouseDownPoint;
 }; // class nsResizerFrame
 
 #endif /* nsResizerFrame_h___ */
--- a/layout/xul/base/src/nsSliderFrame.cpp
+++ b/layout/xul/base/src/nsSliderFrame.cpp
@@ -569,50 +569,16 @@ nsSliderFrame::HandleEvent(nsPresContext
   //   HandleRelease(aPresContext, aEvent, aEventStatus);
 
   if (aEvent->message == NS_MOUSE_EXIT_SYNTH && mChange)
      HandleRelease(aPresContext, aEvent, aEventStatus);
 
   return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
 }
 
-bool
-nsSliderFrame::GetEventPoint(nsGUIEvent* aEvent, nsPoint &aPoint) {
-  nsIntPoint refPoint;
-  nsresult rv;
-  if (aEvent->eventStructType == NS_TOUCH_EVENT) {
-    rv = GetTouchPoint(static_cast<nsTouchEvent*>(aEvent), refPoint);
-    if (NS_FAILED(rv))
-       return false;
-  } else {
-    refPoint = aEvent->refPoint;
-  }
-  aPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, refPoint, this);
-  return true;
-}
-
-bool
-nsSliderFrame::GetTouchPoint(nsTouchEvent* aEvent, nsIntPoint &aPoint)
-{
-  NS_ENSURE_TRUE(aEvent, false);
-  // return false if there is more than one touch on the page, or if
-  // we can't find a touch point
-  if (aEvent->touches.Length() != 1) {
-    return false;
-  }
-
-  nsIDOMTouch *touch = aEvent->touches.SafeElementAt(0);
-  if (!touch) {
-    return false;
-  }
-  nsDOMTouch* domtouch = static_cast<nsDOMTouch*>(touch);
-  aPoint = domtouch->mRefPoint;
-  return true;
-}
-
 // Helper function to collect the "scroll to click" metric. Beware of
 // caching this, users expect to be able to change the system preference
 // and see the browser change its behavior immediately.
 bool
 nsSliderFrame::GetScrollToClick()
 {
   // if there is no parent scrollbar, check the movetoclick attribute. If set
   // to true, always scroll to the click point. If false, never do this.
--- a/layout/xul/base/src/nsSliderFrame.h
+++ b/layout/xul/base/src/nsSliderFrame.h
@@ -134,25 +134,16 @@ private:
                                bool aImmediateRedraw, bool aMaySnap);
   void SetCurrentPosition(nsIContent* aScrollbar, PRInt32 aNewPos, bool aIsSmooth,
                           bool aImmediateRedraw);
   void SetCurrentPositionInternal(nsIContent* aScrollbar, PRInt32 pos,
                                   bool aIsSmooth, bool aImmediateRedraw);
   nsresult CurrentPositionChanged(nsPresContext* aPresContext,
                                   bool aImmediateRedraw);
 
-  // Get the point associated with this event. Returns true if a valid point
-  // was found. Otherwise false.
-  bool GetEventPoint(nsGUIEvent *aEvent, nsPoint &aPoint);
-
-  // Get the point associated with this touch event. Returns true if a valid point
-  // was found. False if there is more than one touch present on the page, or
-  // if a point could not be found for the given touch.
-  bool GetTouchPoint(nsTouchEvent *aEvent, nsIntPoint &aPoint);
-
   void DragThumb(bool aGrabMouseEvents);
   void AddListener();
   void RemoveListener();
   bool isDraggingThumb();
 
   void StartRepeat() {
     nsRepeatService::GetInstance()->Start(Notify, this);
   }
--- a/layout/xul/base/test/Makefile.in
+++ b/layout/xul/base/test/Makefile.in
@@ -17,17 +17,17 @@ MOCHITEST_FILES = 	test_bug511075.html \
 
 MOCHITEST_CHROME_FILES =	test_bug381167.xhtml \
 		test_bug393970.xul \
 		test_bug477754.xul \
 		test_stack.xul \
 		$(NULL)
 
 ifneq (mobile,$(MOZ_BUILD_APP))
-MOCHITEST_FILES = 	test_resizer_incontent.xul
+MOCHITEST_FILES = 	test_resizer_incontent.xul \
 
 MOCHITEST_CHROME_FILES +=	test_resizer.xul \
 		window_resizer.xul \
 		window_resizer_element.xul \
 		$(NULL)
 endif
 
 include $(topsrcdir)/config/rules.mk