merge mozilla-inbound to mozilla-central. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Sun, 01 Oct 2017 11:37:14 +0200
changeset 383886 41286177c59c74ec37961b1edea34cc90d6f6dc5
parent 383884 f90790f7a34616b1e878f3a6f536546e048e21e6 (current diff)
parent 383885 78d84bc21e7cbbeebc9cc2ef3723917f08234bfa (diff)
child 383887 256d7d4e935718f1a11f0afb9383a68ade530eaa
child 383894 a6ce4b7b0721d2d4d7046f6c0b3622280fba50bb
child 383912 320e6535b5e78654b4aa22e5a6a3bd1556c9c234
push id32610
push userarchaeopteryx@coole-files.de
push dateSun, 01 Oct 2017 09:37:30 +0000
treeherdermozilla-central@41286177c59c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone58.0a1
first release with
nightly linux32
41286177c59c / 58.0a1 / 20171001100335 / files
nightly linux64
41286177c59c / 58.0a1 / 20171001100335 / files
nightly mac
41286177c59c / 58.0a1 / 20171001100335 / files
nightly win32
41286177c59c / 58.0a1 / 20171001100335 / files
nightly win64
41286177c59c / 58.0a1 / 20171001100335 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central. r=merge a=merge MozReview-Commit-ID: 6My6YCrpLe9
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -167,26 +167,32 @@ class WidgetRenderingContext;
   // re-establish the connection to the service manager many times per second
   // when handling |draggingUpdated:| messages.
   nsIDragService* mDragService;
 
   NSOpenGLContext *mGLContext;
 
   // Gestures support
   //
+  // mGestureState is used to detect when Cocoa has called both
+  // magnifyWithEvent and rotateWithEvent within the same
+  // beginGestureWithEvent and endGestureWithEvent sequence. We
+  // discard the spurious gesture event so as not to confuse Gecko.
+  //
   // mCumulativeMagnification keeps track of the total amount of
   // magnification peformed during a magnify gesture so that we can
   // send that value with the final MozMagnifyGesture event.
   //
   // mCumulativeRotation keeps track of the total amount of rotation
   // performed during a rotate gesture so we can send that value with
   // the final MozRotateGesture event.
   enum {
     eGestureState_None,
     eGestureState_StartGesture,
+    eGestureState_MagnifyGesture,
     eGestureState_RotateGesture
   } mGestureState;
   float mCumulativeMagnification;
   float mCumulativeRotation;
 
   BOOL mWaitingForPaint;
 
 #ifdef __LP64__
@@ -242,16 +248,17 @@ class WidgetRenderingContext;
  * The prototypes swipeWithEvent, beginGestureWithEvent, smartMagnifyWithEvent,
  * rotateWithEvent and endGestureWithEvent were obtained from the following
  * links:
  * https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSResponder_Class/Reference/Reference.html
  * https://developer.apple.com/library/mac/#releasenotes/Cocoa/AppKit.html
  */
 - (void)swipeWithEvent:(NSEvent *)anEvent;
 - (void)beginGestureWithEvent:(NSEvent *)anEvent;
+- (void)magnifyWithEvent:(NSEvent *)anEvent;
 - (void)smartMagnifyWithEvent:(NSEvent *)anEvent;
 - (void)rotateWithEvent:(NSEvent *)anEvent;
 - (void)endGestureWithEvent:(NSEvent *)anEvent;
 
 - (void)scrollWheel:(NSEvent *)anEvent;
 - (void)handleAsyncScrollEvent:(CGEventRef)cgEvent ofType:(CGEventType)type;
 
 - (void)setUsingOMTCompositor:(BOOL)aUseOMTC;
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -4195,16 +4195,87 @@ NSEvent* gLastDragMouseDownEvent = nil;
     geckoEvent.mDirection |= nsIDOMSimpleGestureEvent::DIRECTION_DOWN;
 
   // Send the event.
   mGeckoChild->DispatchWindowEvent(geckoEvent);
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
+// Pinch zoom gesture.
+- (void)magnifyWithEvent:(NSEvent *)anEvent
+{
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
+
+  if (!anEvent || !mGeckoChild ||
+      [self beginOrEndGestureForEventPhase:anEvent]) {
+    return;
+  }
+
+  nsAutoRetainCocoaObject kungFuDeathGrip(self);
+
+  float deltaZ = [anEvent deltaZ];
+
+  EventMessage msg;
+  switch (mGestureState) {
+  case eGestureState_StartGesture:
+    msg = eMagnifyGestureStart;
+    mGestureState = eGestureState_MagnifyGesture;
+    break;
+
+  case eGestureState_MagnifyGesture:
+    msg = eMagnifyGestureUpdate;
+    break;
+
+  case eGestureState_None:
+  case eGestureState_RotateGesture:
+  default:
+    return;
+  }
+
+  // This sends the pinch gesture value as a fake wheel event that has the
+  // control key pressed so that pages can implement custom pinch gesture
+  // handling. It may seem strange that this doesn't use a wheel event with
+  // the deltaZ property set, but this matches Chrome's behavior as described
+  // at https://code.google.com/p/chromium/issues/detail?id=289887
+  //
+  // The intent of the formula below is to produce numbers similar to Chrome's
+  // implementation of this feature. Chrome implements deltaY using the formula
+  // "-100 * log(1 + [event magnification])" which is unfortunately incorrect.
+  // All deltas for a single pinch gesture should sum to 0 if the start and end
+  // of a pinch gesture end up in the same place. This doesn't happen in Chrome
+  // because they followed Apple's misleading documentation, which implies that
+  // "1 + [event magnification]" is the scale factor. The scale factor is
+  // instead "pow(ratio, [event magnification])" so "[event magnification]" is
+  // already in log space.
+  //
+  // The multiplication by the backing scale factor below counteracts the
+  // division by the backing scale factor in WheelEvent.
+  WidgetWheelEvent geckoWheelEvent(true, EventMessage::eWheel, mGeckoChild);
+  [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoWheelEvent];
+  double backingScale = mGeckoChild->BackingScaleFactor();
+  geckoWheelEvent.mDeltaY = -100.0 * [anEvent magnification] * backingScale;
+  geckoWheelEvent.mModifiers |= MODIFIER_CONTROL;
+  mGeckoChild->DispatchWindowEvent(geckoWheelEvent);
+
+  // If the fake wheel event wasn't stopped, then send a normal magnify event.
+  if (!geckoWheelEvent.mFlags.mDefaultPrevented) {
+    WidgetSimpleGestureEvent geckoEvent(true, msg, mGeckoChild);
+    geckoEvent.mDelta = deltaZ;
+    [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent];
+    mGeckoChild->DispatchWindowEvent(geckoEvent);
+
+    // Keep track of the cumulative magnification for the final "magnify" event.
+    mCumulativeMagnification += deltaZ;
+  }
+
+  NS_OBJC_END_TRY_ABORT_BLOCK;
+}
+
+// Smart zoom gesture, i.e. two-finger double tap on trackpads.
 - (void)smartMagnifyWithEvent:(NSEvent *)anEvent
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   if (!anEvent || !mGeckoChild ||
       [self beginOrEndGestureForEventPhase:anEvent]) {
     return;
   }
@@ -4245,16 +4316,17 @@ NSEvent* gLastDragMouseDownEvent = nil;
     mGestureState = eGestureState_RotateGesture;
     break;
 
   case eGestureState_RotateGesture:
     msg = eRotateGestureUpdate;
     break;
 
   case eGestureState_None:
+  case eGestureState_MagnifyGesture:
   default:
     return;
   }
 
   // Setup the event.
   WidgetSimpleGestureEvent geckoEvent(true, msg, mGeckoChild);
   [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent];
   geckoEvent.mDelta = -rotation;
@@ -4327,16 +4399,28 @@ NSEvent* gLastDragMouseDownEvent = nil;
     mCumulativeMagnification = 0.0;
     mCumulativeRotation = 0.0;
     return;
   }
 
   nsAutoRetainCocoaObject kungFuDeathGrip(self);
 
   switch (mGestureState) {
+  case eGestureState_MagnifyGesture:
+    {
+      // Setup the "magnify" event.
+      WidgetSimpleGestureEvent geckoEvent(true, eMagnifyGesture, mGeckoChild);
+      geckoEvent.mDelta = mCumulativeMagnification;
+      [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent];
+
+      // Send the event.
+      mGeckoChild->DispatchWindowEvent(geckoEvent);
+    }
+    break;
+
   case eGestureState_RotateGesture:
     {
       // Setup the "rotate" event.
       WidgetSimpleGestureEvent geckoEvent(true, eRotateGesture, mGeckoChild);
       [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent];
       geckoEvent.mDelta = -mCumulativeRotation;
       if (mCumulativeRotation > 0.0) {
         geckoEvent.mDirection = nsIDOMSimpleGestureEvent::ROTATION_COUNTERCLOCKWISE;