Bug 668953 - [10.7] Support new back/forward gestures in OSX Lion; r=smichaud
☠☠ backed out by 9c74f840758b ☠ ☠
authorBenoit Girard <b56girard@gmail.com>
Fri, 05 Aug 2011 14:36:51 -0400
changeset 73915 57446cb82caaa789542c3c90c767d8eb8f15bd4a
parent 73914 4d2c4722547c32583819e3bf6caa78b2d0304bc7
child 73916 1c136ef5cac29d4c1f0d209ca547f6d479e217e1
push id20926
push usermak77@bonardo.net
push dateSat, 06 Aug 2011 09:36:25 +0000
treeherdermozilla-central@ba21778fcc14 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmichaud
bugs668953
milestone8.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 668953 - [10.7] Support new back/forward gestures in OSX Lion; r=smichaud
content/events/src/nsEventStateManager.cpp
widget/src/cocoa/Makefile.in
widget/src/cocoa/nsCocoaFeatures.h
widget/src/cocoa/nsCocoaFeatures.mm
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -136,16 +136,20 @@
 #include "mozilla/Services.h"
 #include "mozAutoDocUpdate.h"
 #include "nsHTMLLabelElement.h"
 
 #include "mozilla/Preferences.h"
 
 #ifdef XP_MACOSX
 #import <ApplicationServices/ApplicationServices.h>
+
+#ifdef MOZ_WIDGET_COCOA
+#include "nsCocoaFeatures.h"
+#endif 
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 //#define DEBUG_DOCSHELL_FOCUS
 
 #define NS_USER_INTERACTION_INTERVAL 5000 // ms
@@ -368,25 +372,30 @@ public:
   // Be careful, UpdateTransaction may fire a DOM event, therefore, the target
   // frame might be destroyed in the event handler.
   static PRBool UpdateTransaction(PRInt32 aNumLines,
                                   PRBool aScrollHorizontal);
   static void EndTransaction();
   static void OnEvent(nsEvent* aEvent);
   static void Shutdown();
   static PRUint32 GetTimeoutTime();
+  static PRUint32 GetGestureTimeoutTime();
   static PRInt32 AccelerateWheelDelta(PRInt32 aScrollLines,
                    PRBool aIsHorizontal, PRBool aAllowScrollSpeedOverride,
                    nsIScrollableFrame::ScrollUnit *aScrollQuantity,
                    PRBool aLimitToMaxOnePageScroll = PR_TRUE);
   static PRBool IsAccelerationEnabled();
 
   enum {
     kScrollSeriesTimeout = 80
   };
+#ifdef MOZ_WIDGET_COCOA
+  static PRBool GetGestureTriggered();
+  static void SetGestureTriggered();
+#endif
 protected:
   static nsIntPoint GetScreenPoint(nsGUIEvent* aEvent);
   static void OnFailToScrollTarget();
   static void OnTimeout(nsITimer *aTimer, void *aClosure);
   static void SetTimeout();
   static PRUint32 GetIgnoreMoveDelayTime();
   static PRInt32 GetAccelerationStart();
   static PRInt32 GetAccelerationFactor();
@@ -397,23 +406,29 @@ protected:
                    PRBool aIsHorizontal,
                    nsIScrollableFrame::ScrollUnit *aScrollQuantity);
 
   static nsWeakFrame sTargetFrame;
   static PRUint32    sTime;        // in milliseconds
   static PRUint32    sMouseMoved;  // in milliseconds
   static nsITimer*   sTimer;
   static PRInt32     sScrollSeriesCounter;
+#ifdef MOZ_WIDGET_COCOA
+  static PRUint32    sGestureTriggered; // in milliseconds
+#endif
 };
 
 nsWeakFrame nsMouseWheelTransaction::sTargetFrame(nsnull);
 PRUint32    nsMouseWheelTransaction::sTime        = 0;
 PRUint32    nsMouseWheelTransaction::sMouseMoved  = 0;
 nsITimer*   nsMouseWheelTransaction::sTimer       = nsnull;
 PRInt32     nsMouseWheelTransaction::sScrollSeriesCounter = 0;
+#ifdef MOZ_WIDGET_COCOA
+PRUint32      nsMouseWheelTransaction::sGestureTriggered = 0;
+#endif
 
 static PRBool
 OutOfTime(PRUint32 aBaseTime, PRUint32 aThreshold)
 {
   PRUint32 now = PR_IntervalToMilliseconds(PR_IntervalNow());
   return (now - aBaseTime > aThreshold);
 }
 
@@ -482,18 +497,39 @@ nsMouseWheelTransaction::UpdateTransacti
 
 void
 nsMouseWheelTransaction::EndTransaction()
 {
   if (sTimer)
     sTimer->Cancel();
   sTargetFrame = nsnull;
   sScrollSeriesCounter = 0;
+#ifdef MOZ_WIDGET_COCOA
+  sGestureTriggered = 0;
+#endif
 }
 
+#ifdef MOZ_WIDGET_COCOA
+void
+nsMouseWheelTransaction::SetGestureTriggered() {
+  sGestureTriggered = PR_IntervalToMilliseconds(PR_IntervalNow());
+}
+
+PRBool
+nsMouseWheelTransaction::GetGestureTriggered() {
+  if (sGestureTriggered != 0 &&
+      OutOfTime(sGestureTriggered, GetGestureTimeoutTime())) {
+    // Start accepting new gestures
+    sGestureTriggered = 0;
+  }
+
+  return sGestureTriggered != 0;
+}
+#endif
+
 void
 nsMouseWheelTransaction::OnEvent(nsEvent* aEvent)
 {
   if (!sTargetFrame)
     return;
 
   if (OutOfTime(sTime, GetTimeoutTime())) {
     // Even if the scroll event which is handled after timeout, but onTimeout
@@ -630,16 +666,22 @@ nsIntPoint
 nsMouseWheelTransaction::GetScreenPoint(nsGUIEvent* aEvent)
 {
   NS_ASSERTION(aEvent, "aEvent is null");
   NS_ASSERTION(aEvent->widget, "aEvent-widget is null");
   return aEvent->refPoint + aEvent->widget->WidgetToScreenOffset();
 }
 
 PRUint32
+nsMouseWheelTransaction::GetGestureTimeoutTime()
+{
+  return Preferences::GetUint("mousewheel.transaction.gesturetimeout", 300);
+}
+
+PRUint32
 nsMouseWheelTransaction::GetTimeoutTime()
 {
   return Preferences::GetUint("mousewheel.transaction.timeout", 1500);
 }
 
 PRUint32
 nsMouseWheelTransaction::GetIgnoreMoveDelayTime()
 {
@@ -2792,16 +2834,32 @@ nsEventStateManager::DoScrollText(nsIFra
             passToParent = PR_TRUE;
             nsMouseWheelTransaction::EndTransaction();
           }
         }
       }
     }
   }
 
+#ifdef MOZ_WIDGET_COCOA
+  // On lion scroll will trigger back/forward at the edge of the page
+  if (isHorizontal && passToParent && nsCocoaFeatures::OnLionOrLater()) {
+    if (!nsMouseWheelTransaction::GetGestureTriggered()) {
+      if (numLines > 4 || numLines < -4) {
+        DoScrollHistory(-numLines);
+        nsMouseWheelTransaction::SetGestureTriggered();
+        return NS_OK;
+      }
+    } else {
+      // Extend the gesture in progress
+      nsMouseWheelTransaction::SetGestureTriggered();
+    }
+  }
+#endif
+
   if (!passToParent && frameToScroll) {
     if (aScrollQuantity == nsIScrollableFrame::LINES) {
       // When this is called for querying the scroll target information,
       // we shouldn't limit the scrolling amount to less one page.
       // Otherwise, we shouldn't scroll more one page at once.
       numLines =
         nsMouseWheelTransaction::AccelerateWheelDelta(numLines, isHorizontal,
                                                       aAllowScrollSpeedOverride,
--- a/widget/src/cocoa/Makefile.in
+++ b/widget/src/cocoa/Makefile.in
@@ -52,31 +52,33 @@ GRE_MODULE	= 1
 LIBXUL_LIBRARY = 1
 
 
 
 EXPORTS = \
 		mozView.h \
 		nsChangeObserver.h \
 		nsCocoaUtils.h \
+		nsCocoaFeatures.h \
 		$(NULL)
 
 CMMSRCS = \
   nsBidiKeyboard.mm \
   nsClipboard.mm \
   nsMenuX.mm \
   nsMenuBarX.mm \
   nsMenuItemX.mm \
   nsMenuItemIconX.mm \
   nsMenuUtilsX.mm \
   nsMenuGroupOwnerX.mm \
   nsFilePicker.mm \
   nsDragService.mm \
   nsToolkit.mm \
   nsAppShell.mm \
+  nsCocoaFeatures.mm \
   nsCocoaUtils.mm \
   nsCocoaWindow.mm \
   nsChildView.mm \
   nsWindowMap.mm \
   nsWidgetFactory.mm \
   nsCursorManager.mm \
   nsMacCursor.mm \
   nsScreenCocoa.mm \
new file mode 100644
--- /dev/null
+++ b/widget/src/cocoa/nsCocoaFeatures.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is 
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Benoit Girard <bgirard@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsCocoaFeatures_h_
+#define nsCocoaFeatures_h_
+
+#include "prtypes.h"
+
+class nsCocoaFeatures {
+public:
+  static PRInt32 OSXVersion();
+
+  static PRBool OnSnowLeopardOrLater();  
+  static PRBool OnLionOrLater();  
+private:
+  static PRInt32 mOSXVersion;
+};
+#endif // nsCocoaFeatures_h_
new file mode 100644
--- /dev/null
+++ b/widget/src/cocoa/nsCocoaFeatures.mm
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is thebes gfx code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Benoit Girard <bgirard@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#define MAC_OS_X_VERSION_MASK     0x0000FFFF // Not supported
+#define MAC_OS_X_VERSION_10_4_HEX 0x00001040 // Not supported
+#define MAC_OS_X_VERSION_10_5_HEX 0x00001050
+#define MAC_OS_X_VERSION_10_6_HEX 0x00001060
+#define MAC_OS_X_VERSION_10_7_HEX 0x00001070
+
+// This API will not work for OS X 10.10, see Gestalt.h.
+
+#include "nsCocoaFeatures.h"
+#include "nsDebug.h"
+
+#import <Cocoa/Cocoa.h>
+
+PRInt32 nsCocoaFeatures::mOSXVersion = 0;
+
+/* static */ PRInt32
+nsCocoaFeatures::OSXVersion()
+{
+    if (!mOSXVersion) {
+        // minor version is not accurate, use gestaltSystemVersionMajor, 
+        // gestaltSystemVersionMinor, gestaltSystemVersionBugFix for these
+        OSErr err = ::Gestalt(gestaltSystemVersion, reinterpret_cast<SInt32*>(&mOSXVersion));
+        if (err != noErr) {
+            // This should probably be changed when our minimum version changes
+            NS_ERROR("Couldn't determine OS X version, assuming 10.5");
+            mOSXVersion = MAC_OS_X_VERSION_10_5_HEX;
+        }
+        mOSXVersion &= MAC_OS_X_VERSION_MASK;
+    }
+    return mOSXVersion;
+}
+
+/* static */ PRBool
+nsCocoaFeatures::OnSnowLeopardOrLater()
+{
+    return (OSXVersion() >= MAC_OS_X_VERSION_10_6_HEX);
+}
+
+/* static */ PRBool
+nsCocoaFeatures::OnLionOrLater()
+{
+    return (OSXVersion() >= MAC_OS_X_VERSION_10_7_HEX);
+}
+