From a049539fef02fc13eb3d17109d1ad9daab8083db Mon Sep 17 00:00:00 2001 From: Benoit Girard Date: Fri, 5 Aug 2011 14:36:51 -0400 Subject: [PATCH] Bug 668953 - [10.7] Support new back/forward gestures in OSX Lion; r=smichaud --- content/events/src/nsEventStateManager.cpp | 58 ++++++++++++++++ widget/src/cocoa/Makefile.in | 2 + widget/src/cocoa/nsCocoaFeatures.h | 53 ++++++++++++++ widget/src/cocoa/nsCocoaFeatures.mm | 81 ++++++++++++++++++++++ 4 files changed, 194 insertions(+) create mode 100644 widget/src/cocoa/nsCocoaFeatures.h create mode 100644 widget/src/cocoa/nsCocoaFeatures.mm diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index 30e239af5f2..6cda116b39d 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -141,6 +141,10 @@ #ifdef XP_MACOSX #import + +#ifdef MOZ_WIDGET_COCOA +#include "nsCocoaFeatures.h" +#endif #endif using namespace mozilla; @@ -373,6 +377,7 @@ public: 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, @@ -382,6 +387,10 @@ public: enum { kScrollSeriesTimeout = 80 }; +#ifdef MOZ_WIDGET_COCOA + static PRBool GetGestureTriggered(); + static void SetGestureTriggered(); +#endif protected: static nsIntPoint GetScreenPoint(nsGUIEvent* aEvent); static void OnFailToScrollTarget(); @@ -402,6 +411,9 @@ protected: 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); @@ -409,6 +421,9 @@ 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) @@ -487,8 +502,29 @@ nsMouseWheelTransaction::EndTransaction() 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) { @@ -634,6 +670,12 @@ nsMouseWheelTransaction::GetScreenPoint(nsGUIEvent* aEvent) return aEvent->refPoint + aEvent->widget->WidgetToScreenOffset(); } +PRUint32 +nsMouseWheelTransaction::GetGestureTimeoutTime() +{ + return Preferences::GetUint("mousewheel.transaction.gesturetimeout", 300); +} + PRUint32 nsMouseWheelTransaction::GetTimeoutTime() { @@ -2797,6 +2839,22 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame, } } +#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, diff --git a/widget/src/cocoa/Makefile.in b/widget/src/cocoa/Makefile.in index 63232c70654..c388873b3e8 100644 --- a/widget/src/cocoa/Makefile.in +++ b/widget/src/cocoa/Makefile.in @@ -57,6 +57,7 @@ EXPORTS = \ mozView.h \ nsChangeObserver.h \ nsCocoaUtils.h \ + nsCocoaFeatures.h \ $(NULL) CMMSRCS = \ @@ -72,6 +73,7 @@ CMMSRCS = \ nsDragService.mm \ nsToolkit.mm \ nsAppShell.mm \ + nsCocoaFeatures.mm \ nsCocoaUtils.mm \ nsCocoaWindow.mm \ nsChildView.mm \ diff --git a/widget/src/cocoa/nsCocoaFeatures.h b/widget/src/cocoa/nsCocoaFeatures.h new file mode 100644 index 00000000000..3715eedb578 --- /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 + * + * 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_ diff --git a/widget/src/cocoa/nsCocoaFeatures.mm b/widget/src/cocoa/nsCocoaFeatures.mm new file mode 100644 index 00000000000..5b84bed8b85 --- /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 + * + * 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 + +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(&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); +} +