зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1619187. Handle content prevent defaulting pinch gestures. r=kats
Differential Revision: https://phabricator.services.mozilla.com/D73217
This commit is contained in:
Родитель
2db43533f3
Коммит
f9e267a4a7
|
@ -1720,6 +1720,9 @@ APZEventResult APZCTreeManager::ReceiveInputEvent(InputData& aEvent) {
|
|||
aEvent.mLayersId = hit.mLayersId;
|
||||
hitResult = hit.mHitResult;
|
||||
|
||||
// We always handle pinch gestures as pinch zooms.
|
||||
pinchInput.mHandledByAPZ = true;
|
||||
|
||||
if (hit.mTargetApzc) {
|
||||
MOZ_ASSERT(hitResult != CompositorHitTestInvisibleToHit);
|
||||
|
||||
|
|
|
@ -5026,6 +5026,11 @@ PanGestureBlockState* AsyncPanZoomController::GetCurrentPanGestureBlock()
|
|||
return GetInputQueue()->GetCurrentPanGestureBlock();
|
||||
}
|
||||
|
||||
PinchGestureBlockState* AsyncPanZoomController::GetCurrentPinchGestureBlock()
|
||||
const {
|
||||
return GetInputQueue()->GetCurrentPinchGestureBlock();
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::ResetTouchInputState() {
|
||||
MultiTouchInput cancel(MultiTouchInput::MULTITOUCH_CANCEL, 0,
|
||||
TimeStamp::Now(), 0);
|
||||
|
|
|
@ -1335,6 +1335,7 @@ class AsyncPanZoomController {
|
|||
bool HasReadyTouchBlock() const;
|
||||
|
||||
PanGestureBlockState* GetCurrentPanGestureBlock() const;
|
||||
PinchGestureBlockState* GetCurrentPinchGestureBlock() const;
|
||||
|
||||
private:
|
||||
/* ===================================================================
|
||||
|
|
|
@ -579,6 +579,47 @@ void PanGestureBlockState::SetNeedsToWaitForContentResponse(
|
|||
mWaitingForContentResponse = aWaitForContentResponse;
|
||||
}
|
||||
|
||||
PinchGestureBlockState::PinchGestureBlockState(
|
||||
const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
TargetConfirmationFlags aFlags)
|
||||
: CancelableBlockState(aTargetApzc, aFlags),
|
||||
mInterrupted(false),
|
||||
mWaitingForContentResponse(false) {}
|
||||
|
||||
bool PinchGestureBlockState::MustStayActive() { return true; }
|
||||
|
||||
const char* PinchGestureBlockState::Type() { return "pinch gesture"; }
|
||||
|
||||
bool PinchGestureBlockState::SetContentResponse(bool aPreventDefault) {
|
||||
if (aPreventDefault) {
|
||||
TBS_LOG("%p setting interrupted flag\n", this);
|
||||
mInterrupted = true;
|
||||
}
|
||||
bool stateChanged = CancelableBlockState::SetContentResponse(aPreventDefault);
|
||||
if (mWaitingForContentResponse) {
|
||||
mWaitingForContentResponse = false;
|
||||
stateChanged = true;
|
||||
}
|
||||
return stateChanged;
|
||||
}
|
||||
|
||||
bool PinchGestureBlockState::HasReceivedAllContentNotifications() const {
|
||||
return CancelableBlockState::HasReceivedAllContentNotifications() &&
|
||||
!mWaitingForContentResponse;
|
||||
}
|
||||
|
||||
bool PinchGestureBlockState::IsReadyForHandling() const {
|
||||
if (!CancelableBlockState::IsReadyForHandling()) {
|
||||
return false;
|
||||
}
|
||||
return !mWaitingForContentResponse || IsContentResponseTimerExpired();
|
||||
}
|
||||
|
||||
void PinchGestureBlockState::SetNeedsToWaitForContentResponse(
|
||||
bool aWaitForContentResponse) {
|
||||
mWaitingForContentResponse = aWaitForContentResponse;
|
||||
}
|
||||
|
||||
TouchBlockState::TouchBlockState(
|
||||
const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
TargetConfirmationFlags aFlags, TouchCounter& aCounter)
|
||||
|
|
|
@ -29,6 +29,7 @@ class TouchBlockState;
|
|||
class WheelBlockState;
|
||||
class DragBlockState;
|
||||
class PanGestureBlockState;
|
||||
class PinchGestureBlockState;
|
||||
class KeyboardBlockState;
|
||||
|
||||
/**
|
||||
|
@ -59,6 +60,7 @@ class InputBlockState : public RefCounted<InputBlockState> {
|
|||
virtual WheelBlockState* AsWheelBlock() { return nullptr; }
|
||||
virtual DragBlockState* AsDragBlock() { return nullptr; }
|
||||
virtual PanGestureBlockState* AsPanGestureBlock() { return nullptr; }
|
||||
virtual PinchGestureBlockState* AsPinchGestureBlock() { return nullptr; }
|
||||
virtual KeyboardBlockState* AsKeyboardBlock() { return nullptr; }
|
||||
|
||||
virtual bool SetConfirmedTargetApzc(
|
||||
|
@ -357,6 +359,31 @@ class PanGestureBlockState : public CancelableBlockState {
|
|||
ScrollDirections mAllowedScrollDirections;
|
||||
};
|
||||
|
||||
/**
|
||||
* A single block of pinch gesture events.
|
||||
*/
|
||||
class PinchGestureBlockState : public CancelableBlockState {
|
||||
public:
|
||||
PinchGestureBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
TargetConfirmationFlags aFlags);
|
||||
|
||||
bool SetContentResponse(bool aPreventDefault) override;
|
||||
bool HasReceivedAllContentNotifications() const override;
|
||||
bool IsReadyForHandling() const override;
|
||||
bool MustStayActive() override;
|
||||
const char* Type() override;
|
||||
|
||||
PinchGestureBlockState* AsPinchGestureBlock() override { return this; }
|
||||
|
||||
bool WasInterrupted() const { return mInterrupted; }
|
||||
|
||||
void SetNeedsToWaitForContentResponse(bool aWaitForContentResponse);
|
||||
|
||||
private:
|
||||
bool mInterrupted;
|
||||
bool mWaitingForContentResponse;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class represents a single touch block. A touch block is
|
||||
* a set of touch events that can be cancelled by web content via
|
||||
|
|
|
@ -52,6 +52,11 @@ nsEventStatus InputQueue::ReceiveInputEvent(
|
|||
return ReceivePanGestureInput(aTarget, aFlags, event, aOutInputBlockId);
|
||||
}
|
||||
|
||||
case PINCHGESTURE_INPUT: {
|
||||
const PinchGestureInput& event = aEvent.AsPinchGestureInput();
|
||||
return ReceivePinchGestureInput(aTarget, aFlags, event, aOutInputBlockId);
|
||||
}
|
||||
|
||||
case MOUSE_INPUT: {
|
||||
const MouseInput& event = aEvent.AsMouseInput();
|
||||
return ReceiveMouseInput(aTarget, aFlags, event, aOutInputBlockId);
|
||||
|
@ -410,6 +415,54 @@ nsEventStatus InputQueue::ReceivePanGestureInput(
|
|||
return result;
|
||||
}
|
||||
|
||||
nsEventStatus InputQueue::ReceivePinchGestureInput(
|
||||
const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
TargetConfirmationFlags aFlags, const PinchGestureInput& aEvent,
|
||||
uint64_t* aOutInputBlockId) {
|
||||
PinchGestureBlockState* block = nullptr;
|
||||
if (aEvent.mType != PinchGestureInput::PINCHGESTURE_START) {
|
||||
block = mActivePinchGestureBlock.get();
|
||||
}
|
||||
|
||||
nsEventStatus result = nsEventStatus_eConsumeDoDefault;
|
||||
|
||||
if (!block || block->WasInterrupted()) {
|
||||
if (aEvent.mType != PinchGestureInput::PINCHGESTURE_START) {
|
||||
// Only PINCHGESTURE_START events are allowed to start a new pinch gesture
|
||||
// block.
|
||||
INPQ_LOG("pinchgesture block %p was interrupted %d\n", block,
|
||||
block ? block->WasInterrupted() : 0);
|
||||
return nsEventStatus_eConsumeDoDefault;
|
||||
}
|
||||
block = new PinchGestureBlockState(aTarget, aFlags);
|
||||
INPQ_LOG("started new pinch gesture block %p id %" PRIu64
|
||||
" for target %p\n",
|
||||
block, block->GetBlockId(), aTarget.get());
|
||||
|
||||
mActivePinchGestureBlock = block;
|
||||
block->SetNeedsToWaitForContentResponse(true);
|
||||
|
||||
CancelAnimationsForNewBlock(block);
|
||||
MaybeRequestContentResponse(aTarget, block);
|
||||
} else {
|
||||
INPQ_LOG("received new event in block %p\n", block);
|
||||
}
|
||||
|
||||
if (aOutInputBlockId) {
|
||||
*aOutInputBlockId = block->GetBlockId();
|
||||
}
|
||||
|
||||
// Note that the |aTarget| the APZCTM sent us may contradict the confirmed
|
||||
// target set on the block. In this case the confirmed target (which may be
|
||||
// null) should take priority. This is equivalent to just always using the
|
||||
// target (confirmed or not) from the block, which is what
|
||||
// ProcessQueue() does.
|
||||
mQueuedInputs.AppendElement(MakeUnique<QueuedInput>(aEvent, *block));
|
||||
ProcessQueue();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void InputQueue::CancelAnimationsForNewBlock(InputBlockState* aBlock,
|
||||
CancelAnimationFlags aExtraFlags) {
|
||||
// We want to cancel animations here as soon as possible (i.e. without waiting
|
||||
|
@ -504,6 +557,11 @@ PanGestureBlockState* InputQueue::GetCurrentPanGestureBlock() const {
|
|||
return block ? block->AsPanGestureBlock() : mActivePanGestureBlock.get();
|
||||
}
|
||||
|
||||
PinchGestureBlockState* InputQueue::GetCurrentPinchGestureBlock() const {
|
||||
InputBlockState* block = GetCurrentBlock();
|
||||
return block ? block->AsPinchGestureBlock() : mActivePinchGestureBlock.get();
|
||||
}
|
||||
|
||||
KeyboardBlockState* InputQueue::GetCurrentKeyboardBlock() const {
|
||||
InputBlockState* block = GetCurrentBlock();
|
||||
return block ? block->AsKeyboardBlock() : mActiveKeyboardBlock.get();
|
||||
|
@ -596,6 +654,9 @@ InputBlockState* InputQueue::FindBlockForId(uint64_t aInputBlockId,
|
|||
} else if (mActivePanGestureBlock &&
|
||||
mActivePanGestureBlock->GetBlockId() == aInputBlockId) {
|
||||
block = mActivePanGestureBlock.get();
|
||||
} else if (mActivePinchGestureBlock &&
|
||||
mActivePinchGestureBlock->GetBlockId() == aInputBlockId) {
|
||||
block = mActivePinchGestureBlock.get();
|
||||
} else if (mActiveKeyboardBlock &&
|
||||
mActiveKeyboardBlock->GetBlockId() == aInputBlockId) {
|
||||
block = mActiveKeyboardBlock.get();
|
||||
|
@ -780,6 +841,9 @@ void InputQueue::ProcessQueue() {
|
|||
if (CanDiscardBlock(mActivePanGestureBlock)) {
|
||||
mActivePanGestureBlock = nullptr;
|
||||
}
|
||||
if (CanDiscardBlock(mActivePinchGestureBlock)) {
|
||||
mActivePinchGestureBlock = nullptr;
|
||||
}
|
||||
if (CanDiscardBlock(mActiveKeyboardBlock)) {
|
||||
mActiveKeyboardBlock = nullptr;
|
||||
}
|
||||
|
@ -815,6 +879,7 @@ void InputQueue::Clear() {
|
|||
mActiveWheelBlock = nullptr;
|
||||
mActiveDragBlock = nullptr;
|
||||
mActivePanGestureBlock = nullptr;
|
||||
mActivePinchGestureBlock = nullptr;
|
||||
mActiveKeyboardBlock = nullptr;
|
||||
mLastActiveApzc = nullptr;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ class TouchBlockState;
|
|||
class WheelBlockState;
|
||||
class DragBlockState;
|
||||
class PanGestureBlockState;
|
||||
class PinchGestureBlockState;
|
||||
class KeyboardBlockState;
|
||||
class AsyncDragMetrics;
|
||||
class QueuedInput;
|
||||
|
@ -112,6 +113,7 @@ class InputQueue {
|
|||
WheelBlockState* GetCurrentWheelBlock() const;
|
||||
DragBlockState* GetCurrentDragBlock() const;
|
||||
PanGestureBlockState* GetCurrentPanGestureBlock() const;
|
||||
PinchGestureBlockState* GetCurrentPinchGestureBlock() const;
|
||||
KeyboardBlockState* GetCurrentKeyboardBlock() const;
|
||||
/**
|
||||
* Returns true iff the pending block at the head of the queue is a touch
|
||||
|
@ -189,6 +191,10 @@ class InputQueue {
|
|||
const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
TargetConfirmationFlags aFlags, const PanGestureInput& aEvent,
|
||||
uint64_t* aOutInputBlockId);
|
||||
nsEventStatus ReceivePinchGestureInput(
|
||||
const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
TargetConfirmationFlags aFlags, const PinchGestureInput& aEvent,
|
||||
uint64_t* aOutInputBlockId);
|
||||
nsEventStatus ReceiveKeyboardInput(
|
||||
const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
const KeyboardInput& aEvent, uint64_t* aOutInputBlockId);
|
||||
|
@ -225,6 +231,7 @@ class InputQueue {
|
|||
RefPtr<WheelBlockState> mActiveWheelBlock;
|
||||
RefPtr<DragBlockState> mActiveDragBlock;
|
||||
RefPtr<PanGestureBlockState> mActivePanGestureBlock;
|
||||
RefPtr<PinchGestureBlockState> mActivePinchGestureBlock;
|
||||
RefPtr<KeyboardBlockState> mActiveKeyboardBlock;
|
||||
|
||||
// The APZC to which the last event was delivered
|
||||
|
|
|
@ -28,6 +28,10 @@ QueuedInput::QueuedInput(const PanGestureInput& aInput,
|
|||
PanGestureBlockState& aBlock)
|
||||
: mInput(MakeUnique<PanGestureInput>(aInput)), mBlock(&aBlock) {}
|
||||
|
||||
QueuedInput::QueuedInput(const PinchGestureInput& aInput,
|
||||
PinchGestureBlockState& aBlock)
|
||||
: mInput(MakeUnique<PinchGestureInput>(aInput)), mBlock(&aBlock) {}
|
||||
|
||||
QueuedInput::QueuedInput(const KeyboardInput& aInput,
|
||||
KeyboardBlockState& aBlock)
|
||||
: mInput(MakeUnique<KeyboardInput>(aInput)), mBlock(&aBlock) {}
|
||||
|
|
|
@ -39,6 +39,7 @@ class QueuedInput {
|
|||
QueuedInput(const ScrollWheelInput& aInput, WheelBlockState& aBlock);
|
||||
QueuedInput(const MouseInput& aInput, DragBlockState& aBlock);
|
||||
QueuedInput(const PanGestureInput& aInput, PanGestureBlockState& aBlock);
|
||||
QueuedInput(const PinchGestureInput& aInput, PinchGestureBlockState& aBlock);
|
||||
QueuedInput(const KeyboardInput& aInput, KeyboardBlockState& aBlock);
|
||||
|
||||
InputData* Input();
|
||||
|
|
|
@ -537,7 +537,9 @@ ParentLayerPoint PanGestureInput::UserMultipliedLocalPanDisplacement() const {
|
|||
}
|
||||
|
||||
PinchGestureInput::PinchGestureInput()
|
||||
: InputData(PINCHGESTURE_INPUT), mType(PINCHGESTURE_START) {}
|
||||
: InputData(PINCHGESTURE_INPUT),
|
||||
mType(PINCHGESTURE_START),
|
||||
mHandledByAPZ(false) {}
|
||||
|
||||
PinchGestureInput::PinchGestureInput(
|
||||
PinchGestureType aType, uint32_t aTime, TimeStamp aTimeStamp,
|
||||
|
@ -548,7 +550,8 @@ PinchGestureInput::PinchGestureInput(
|
|||
mFocusPoint(aFocusPoint),
|
||||
mScreenOffset(aScreenOffset),
|
||||
mCurrentSpan(aCurrentSpan),
|
||||
mPreviousSpan(aPreviousSpan) {}
|
||||
mPreviousSpan(aPreviousSpan),
|
||||
mHandledByAPZ(false) {}
|
||||
|
||||
bool PinchGestureInput::TransformToLocal(
|
||||
const ScreenToParentLayerMatrix4x4& aTransform) {
|
||||
|
@ -565,6 +568,74 @@ bool PinchGestureInput::TransformToLocal(
|
|||
return true;
|
||||
}
|
||||
|
||||
WidgetWheelEvent PinchGestureInput::ToWidgetWheelEvent(
|
||||
nsIWidget* aWidget) const {
|
||||
WidgetWheelEvent wheelEvent(true, eWheel, aWidget);
|
||||
wheelEvent.mModifiers = this->modifiers | MODIFIER_CONTROL;
|
||||
wheelEvent.mTime = mTime;
|
||||
wheelEvent.mTimeStamp = mTimeStamp;
|
||||
wheelEvent.mRefPoint = RoundedToInt(ViewAs<LayoutDevicePixel>(
|
||||
mFocusPoint,
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
|
||||
wheelEvent.mButtons = 0;
|
||||
wheelEvent.mFlags.mHandledByAPZ = mHandledByAPZ;
|
||||
wheelEvent.mDeltaMode = WheelEvent_Binding::DOM_DELTA_PIXEL;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// This converts the pinch gesture value to 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.
|
||||
|
||||
// We want to set deltaY to |-100.0 * M * GetDefaultScaleInternal()| where M
|
||||
// is [event magnification] but [event magnification] is only available in the
|
||||
// macOS widget code so we have to reverse engineer from mCurrentSpan and
|
||||
// mPreviousSpan (which are derived from [event magnification]) to get it.
|
||||
// Specifically, we know |mCurrentSpan == 100.0| and |mPreviousSpan == 100.0 *
|
||||
// (1.0 - M)|. We can calculate deltaY by solving the mPreviousSpan equation
|
||||
// for M in terms of mPreviousSpan and plugging that into to the formula for
|
||||
// deltaY.
|
||||
wheelEvent.mDeltaY = (mPreviousSpan - 100.0) *
|
||||
(aWidget ? aWidget->GetDefaultScaleInternal() : 1.f);
|
||||
#else
|
||||
// This calculation is based on what the Windows widget code does.
|
||||
// Specifically, it creates a PinchGestureInput with |mCurrentSpan == 100.0 *
|
||||
// currentScale| and |mPreviousSpan == 100.0 * lastScale| where currentScale
|
||||
// is the scale from the current OS event and lastScale is the scale when the
|
||||
// previous OS event happened. It then seems reasonable to calculate |M =
|
||||
// currentScale / lastScale| and use the same formula as the macOS code
|
||||
// (|-100.0 * M * GetDefaultScaleInternal()|).
|
||||
|
||||
// XXX When we write the code for other platforms to do the same we'll need to
|
||||
// make sure this calculation is reasonable.
|
||||
|
||||
if (mPreviousSpan != 0.f) {
|
||||
wheelEvent.mDeltaY = -100.0 * (mCurrentSpan / mPreviousSpan) *
|
||||
(aWidget ? aWidget->GetDefaultScaleInternal() : 1.f);
|
||||
} else {
|
||||
// Not sure what makes sense here, this seems reasonable.
|
||||
wheelEvent.mDeltaY = -100.0 * mCurrentSpan *
|
||||
(aWidget ? aWidget->GetDefaultScaleInternal() : 1.f);
|
||||
}
|
||||
#endif
|
||||
|
||||
return wheelEvent;
|
||||
}
|
||||
|
||||
TapGestureInput::TapGestureInput()
|
||||
: InputData(TAPGESTURE_INPUT), mType(TAPGESTURE_LONG) {}
|
||||
|
||||
|
|
|
@ -452,6 +452,8 @@ class PinchGestureInput : public InputData {
|
|||
|
||||
bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
|
||||
|
||||
WidgetWheelEvent ToWidgetWheelEvent(nsIWidget* aWidget) const;
|
||||
|
||||
// Warning, this class is serialized and sent over IPC. Any change to its
|
||||
// fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h
|
||||
PinchGestureType mType;
|
||||
|
@ -482,6 +484,8 @@ class PinchGestureInput : public InputData {
|
|||
// of this type then there must have been a history of spans.
|
||||
ScreenCoord mPreviousSpan;
|
||||
|
||||
bool mHandledByAPZ;
|
||||
|
||||
// A special value for mFocusPoint used in PINCHGESTURE_END events to
|
||||
// indicate that both fingers have been lifted. If only one finger has
|
||||
// been lifted, the coordinates of the remaining finger are expected to
|
||||
|
|
|
@ -2049,10 +2049,23 @@ void nsChildView::ReportSwipeStarted(uint64_t aInputBlockId, bool aStartSwipe) {
|
|||
}
|
||||
|
||||
nsEventStatus nsChildView::DispatchAPZInputEvent(InputData& aEvent) {
|
||||
APZEventResult result;
|
||||
|
||||
if (mAPZC) {
|
||||
return mAPZC->InputBridge()->ReceiveInputEvent(aEvent).mStatus;
|
||||
result = mAPZC->InputBridge()->ReceiveInputEvent(aEvent);
|
||||
}
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
if (result.mStatus == nsEventStatus_eConsumeNoDefault) {
|
||||
return result.mStatus;
|
||||
}
|
||||
|
||||
if (aEvent.mInputType == PINCHGESTURE_INPUT) {
|
||||
PinchGestureInput& pinchEvent = aEvent.AsPinchGestureInput();
|
||||
WidgetWheelEvent wheelEvent = pinchEvent.ToWidgetWheelEvent(this);
|
||||
ProcessUntransformedAPZEvent(&wheelEvent, result);
|
||||
}
|
||||
|
||||
return result.mStatus;
|
||||
}
|
||||
|
||||
void nsChildView::DispatchAPZWheelInputEvent(InputData& aEvent, bool aCanTriggerSwipe) {
|
||||
|
@ -2791,53 +2804,53 @@ NSEvent* gLastDragMouseDownEvent = nil; // [strong]
|
|||
return;
|
||||
}
|
||||
|
||||
NSPoint locationInWindow = nsCocoaUtils::EventLocationForWindow(anEvent, [self window]);
|
||||
ScreenPoint position =
|
||||
ViewAs<ScreenPixel>([self convertWindowCoordinatesRoundDown:locationInWindow],
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent);
|
||||
ExternalPoint screenOffset =
|
||||
ViewAs<ExternalPixel>(mGeckoChild->WidgetToScreenOffset(),
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent);
|
||||
|
||||
PRIntervalTime eventIntervalTime = PR_IntervalNow();
|
||||
TimeStamp eventTimeStamp = nsCocoaUtils::GetEventTimeStamp([anEvent timestamp]);
|
||||
NSEventPhase eventPhase = [anEvent phase];
|
||||
PinchGestureInput::PinchGestureType pinchGestureType;
|
||||
|
||||
switch (eventPhase) {
|
||||
case NSEventPhaseBegan: {
|
||||
pinchGestureType = PinchGestureInput::PINCHGESTURE_START;
|
||||
break;
|
||||
}
|
||||
case NSEventPhaseChanged: {
|
||||
pinchGestureType = PinchGestureInput::PINCHGESTURE_SCALE;
|
||||
break;
|
||||
}
|
||||
case NSEventPhaseEnded: {
|
||||
pinchGestureType = PinchGestureInput::PINCHGESTURE_END;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
NS_WARNING("Unexpected phase for pinch gesture event.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PinchGestureInput event{pinchGestureType,
|
||||
eventIntervalTime,
|
||||
eventTimeStamp,
|
||||
screenOffset,
|
||||
position,
|
||||
100.0,
|
||||
100.0 * (1.0 - [anEvent magnification]),
|
||||
nsCocoaUtils::ModifiersForEvent(anEvent)};
|
||||
|
||||
if (pinchGestureType == PinchGestureInput::PINCHGESTURE_END) {
|
||||
event.mFocusPoint = PinchGestureInput::BothFingersLifted<ScreenPixel>();
|
||||
}
|
||||
|
||||
// FIXME: bug 1525793 -- this may need to handle zooming or not on a per-document basis.
|
||||
if (StaticPrefs::apz_allow_zooming()) {
|
||||
NSPoint locationInWindow = nsCocoaUtils::EventLocationForWindow(anEvent, [self window]);
|
||||
ScreenPoint position =
|
||||
ViewAs<ScreenPixel>([self convertWindowCoordinatesRoundDown:locationInWindow],
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent);
|
||||
ExternalPoint screenOffset =
|
||||
ViewAs<ExternalPixel>(mGeckoChild->WidgetToScreenOffset(),
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent);
|
||||
|
||||
PRIntervalTime eventIntervalTime = PR_IntervalNow();
|
||||
TimeStamp eventTimeStamp = nsCocoaUtils::GetEventTimeStamp([anEvent timestamp]);
|
||||
NSEventPhase eventPhase = [anEvent phase];
|
||||
PinchGestureInput::PinchGestureType pinchGestureType;
|
||||
|
||||
switch (eventPhase) {
|
||||
case NSEventPhaseBegan: {
|
||||
pinchGestureType = PinchGestureInput::PINCHGESTURE_START;
|
||||
break;
|
||||
}
|
||||
case NSEventPhaseChanged: {
|
||||
pinchGestureType = PinchGestureInput::PINCHGESTURE_SCALE;
|
||||
break;
|
||||
}
|
||||
case NSEventPhaseEnded: {
|
||||
pinchGestureType = PinchGestureInput::PINCHGESTURE_END;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
NS_WARNING("Unexpected phase for pinch gesture event.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PinchGestureInput event{pinchGestureType,
|
||||
eventIntervalTime,
|
||||
eventTimeStamp,
|
||||
screenOffset,
|
||||
position,
|
||||
100.0,
|
||||
100.0 * (1.0 - [anEvent magnification]),
|
||||
nsCocoaUtils::ModifiersForEvent(anEvent)};
|
||||
|
||||
if (pinchGestureType == PinchGestureInput::PINCHGESTURE_END) {
|
||||
event.mFocusPoint = PinchGestureInput::BothFingersLifted<ScreenPixel>();
|
||||
}
|
||||
|
||||
mGeckoChild->DispatchAPZInputEvent(event);
|
||||
} else {
|
||||
if (!anEvent || [self beginOrEndGestureForEventPhase:anEvent]) {
|
||||
|
@ -2865,29 +2878,10 @@ NSEvent* gLastDragMouseDownEvent = nil; // [strong]
|
|||
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;
|
||||
// See PinchGestureInput::ToWidgetWheelEvent for a lengthy explanation of the values we put into
|
||||
// the WidgetWheelEvent that used to be here.
|
||||
|
||||
WidgetWheelEvent geckoWheelEvent(event.ToWidgetWheelEvent(mGeckoChild));
|
||||
mGeckoChild->DispatchWindowEvent(geckoWheelEvent);
|
||||
|
||||
// If the fake wheel event wasn't stopped, then send a normal magnify event.
|
||||
|
|
|
@ -1297,6 +1297,7 @@ struct ParamTraits<mozilla::PinchGestureInput> {
|
|||
WriteParam(aMsg, aParam.mLocalFocusPoint);
|
||||
WriteParam(aMsg, aParam.mCurrentSpan);
|
||||
WriteParam(aMsg, aParam.mPreviousSpan);
|
||||
WriteParam(aMsg, aParam.mHandledByAPZ);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
|
@ -1307,7 +1308,8 @@ struct ParamTraits<mozilla::PinchGestureInput> {
|
|||
ReadParam(aMsg, aIter, &aResult->mFocusPoint) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mLocalFocusPoint) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mCurrentSpan) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mPreviousSpan);
|
||||
ReadParam(aMsg, aIter, &aResult->mPreviousSpan) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHandledByAPZ);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -2155,13 +2155,13 @@ class nsIWidget : public nsISupports {
|
|||
|
||||
static already_AddRefed<nsIBidiKeyboard> CreateBidiKeyboard();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Like GetDefaultScale, but taking into account only the system settings
|
||||
* and ignoring Gecko preferences.
|
||||
*/
|
||||
virtual double GetDefaultScaleInternal() { return 1.0; }
|
||||
|
||||
protected:
|
||||
// keep the list of children. We also keep track of our siblings.
|
||||
// The ownership model is as follows: parent holds a strong ref to
|
||||
// the first element of the list, and each element holds a strong
|
||||
|
|
Загрузка…
Ссылка в новой задаче